nsc: enable network simulation cradle
authorFlorian Westphal <fw@strlen.de>
Fri, 29 Aug 2008 23:10:00 +0200
changeset 3579 9e5eaef3e082
parent 3578 e6374560e19e
child 3580 5818912ae9a3
nsc: enable network simulation cradle This adds the hooks to allow the nsc code to be compiled into ns-3 if the --nsc flag is specified during 'waf configure'.
src/helper/internet-stack-helper.cc
src/helper/internet-stack-helper.h
src/internet-stack/internet-stack.cc
src/internet-stack/internet-stack.h
src/internet-stack/wscript
src/wscript
wscript
--- a/src/helper/internet-stack-helper.cc	Fri Aug 29 23:08:18 2008 +0200
+++ b/src/helper/internet-stack-helper.cc	Fri Aug 29 23:10:00 2008 +0200
@@ -33,6 +33,10 @@
 std::vector<InternetStackHelper::Trace> InternetStackHelper::m_traces;
 std::string InternetStackHelper::m_pcapBaseFilename;
 
+InternetStackHelper::InternetStackHelper() : m_nscLibrary("")
+{
+}
+
 void
 InternetStackHelper::Cleanup (void)
 {
@@ -48,6 +52,12 @@
   m_traces.clear ();
 }
 
+void
+InternetStackHelper::SetNscStack(const std::string soname)
+{
+  m_nscLibrary = soname;
+}
+
 void 
 InternetStackHelper::Install (NodeContainer c)
 {
@@ -59,8 +69,12 @@
           NS_FATAL_ERROR ("InternetStackHelper::Install(): Aggregating " 
              "an InternetStack to a node with an existing Ipv4 object");
           return;
-        } 
-      AddInternetStack (node);
+        }
+      if (m_nscLibrary != "")
+        AddNscInternetStack (node, m_nscLibrary);
+      else
+        AddInternetStack (node);
+
       Ptr<PacketSocketFactory> factory = CreateObject<PacketSocketFactory> ();
       node->AggregateObject (factory);
     }
--- a/src/helper/internet-stack-helper.h	Fri Aug 29 23:08:18 2008 +0200
+++ b/src/helper/internet-stack-helper.h	Fri Aug 29 23:10:00 2008 +0200
@@ -33,6 +33,8 @@
 class InternetStackHelper
 {
 public:
+  InternetStackHelper(void);
+
   /**
    * \param c the set of nodes
    *
@@ -45,6 +47,13 @@
   void Install (NodeContainer c);
 
   /**
+   * \param soname name of the shared library with the nsc tcp stack
+   * to use, e.g. 'liblinux2.6.26.so'. The empty string resets
+   * the InternetStackHelper to use the ns-3 models again.
+   */
+  void SetNscStack(std::string soname);
+
+  /**
    * \param filename filename prefix to use for pcap files.
    *
    * Enable pcap output on each protocol instance which is of the
@@ -60,6 +69,7 @@
   static void EnablePcapAll (std::string filename);
 
 private:
+  std::string m_nscLibrary;
   static void Cleanup (void);
   static void LogRxIp (std::string context, Ptr<const Packet> packet, uint32_t deviceId);
   static void LogTxIp (std::string context, Ptr<const Packet> packet, uint32_t deviceId);
--- a/src/internet-stack/internet-stack.cc	Fri Aug 29 23:08:18 2008 +0200
+++ b/src/internet-stack/internet-stack.cc	Fri Aug 29 23:10:00 2008 +0200
@@ -21,6 +21,7 @@
 #include "ns3/net-device.h"
 #include "ns3/callback.h"
 #include "ns3/node.h"
+#include "ns3/core-config.h"
 
 #include "ipv4-l4-demux.h"
 #include "udp-l4-protocol.h"
@@ -31,41 +32,105 @@
 #include "tcp-socket-factory-impl.h"
 #include "ipv4-impl.h"
 
+#ifdef NETWORK_SIMULATION_CRADLE
+#include "nsc-tcp-socket-factory-impl.h"
+#include "nsc-tcp-l4-protocol.h"
+#endif
+
 namespace ns3 {
 
-void 
+static void
+AddArpStack (Ptr<Node> node)
+{
+  Ptr<ArpL3Protocol> arp = CreateObject<ArpL3Protocol> ();
+  arp->SetNode (node);
+  node->AggregateObject (arp);
+}
+
+static void
+AddUdpStack(Ptr<Node> node, Ptr<Ipv4L4Demux> ipv4L4Demux)
+{
+  Ptr<UdpL4Protocol> udp = CreateObject<UdpL4Protocol> ();
+  udp->SetNode (node);
+  ipv4L4Demux->Insert (udp);
+  Ptr<UdpSocketFactoryImpl> udpFactory = CreateObject<UdpSocketFactoryImpl> ();
+  udpFactory->SetUdp (udp);
+  node->AggregateObject (udpFactory);
+}
+
+static void
+AddTcpStack(Ptr<Node> node, Ptr<Ipv4L4Demux> ipv4L4Demux)
+{
+  Ptr<TcpL4Protocol> tcp = CreateObject<TcpL4Protocol> ();
+  tcp->SetNode (node);
+  ipv4L4Demux->Insert (tcp);
+  Ptr<TcpSocketFactoryImpl> tcpFactory = CreateObject<TcpSocketFactoryImpl> ();
+  tcpFactory->SetTcp (tcp);
+  node->AggregateObject (tcpFactory);
+}
+
+static void
+AddIpv4Impl(Ptr<Node> node, Ptr<Ipv4L3Protocol> ipv4)
+{
+  Ptr<Ipv4Impl> ipv4Impl = CreateObject<Ipv4Impl> ();
+  ipv4Impl->SetIpv4 (ipv4);
+  node->AggregateObject (ipv4);
+  node->AggregateObject (ipv4Impl);
+}
+
+void
 AddInternetStack (Ptr<Node> node)
 {
+  AddArpStack(node);
   Ptr<Ipv4L3Protocol> ipv4 = CreateObject<Ipv4L3Protocol> ();
-  Ptr<ArpL3Protocol> arp = CreateObject<ArpL3Protocol> ();
   ipv4->SetNode (node);
-  arp->SetNode (node);
 
   Ptr<Ipv4L4Demux> ipv4L4Demux = CreateObject<Ipv4L4Demux> ();
-  Ptr<UdpL4Protocol> udp = CreateObject<UdpL4Protocol> ();
-  Ptr<TcpL4Protocol> tcp = CreateObject<TcpL4Protocol> ();
-
   ipv4L4Demux->SetNode (node);
-  udp->SetNode (node);
-  tcp->SetNode (node);
-
-  ipv4L4Demux->Insert (udp);
-  ipv4L4Demux->Insert (tcp);
 
-  Ptr<UdpSocketFactoryImpl> udpFactory = CreateObject<UdpSocketFactoryImpl> ();
-  Ptr<TcpSocketFactoryImpl> tcpFactory = CreateObject<TcpSocketFactoryImpl> ();
-  Ptr<Ipv4Impl> ipv4Impl = CreateObject<Ipv4Impl> ();
+  AddUdpStack (node, ipv4L4Demux);
+  AddTcpStack (node, ipv4L4Demux);
 
-  udpFactory->SetUdp (udp);
-  tcpFactory->SetTcp (tcp);
-  ipv4Impl->SetIpv4 (ipv4);
-
-  node->AggregateObject (ipv4);
-  node->AggregateObject (arp);
-  node->AggregateObject (ipv4Impl);
-  node->AggregateObject (udpFactory);
-  node->AggregateObject (tcpFactory);
+  AddIpv4Impl (node, ipv4);
   node->AggregateObject (ipv4L4Demux);
 }
 
+
+#ifdef NETWORK_SIMULATION_CRADLE
+static void
+AddNscStack(Ptr<Node> node, Ptr<Ipv4L4Demux> ipv4L4Demux, const std::string &soname)
+{
+  Ptr<NscTcpL4Protocol> tcp = CreateObject<NscTcpL4Protocol> ();
+  tcp->SetNscLibrary(soname);
+  tcp->SetNode (node);
+  ipv4L4Demux->Insert (tcp);
+  Ptr<NscTcpSocketFactoryImpl> tcpFactory = CreateObject<NscTcpSocketFactoryImpl> ();
+  tcpFactory->SetTcp (tcp);
+  node->AggregateObject (tcpFactory);
+}
+
+
+void
+AddNscInternetStack (Ptr<Node> node, const std::string &soname)
+{
+  AddArpStack(node);
+  Ptr<Ipv4L3Protocol> ipv4 = CreateObject<Ipv4L3Protocol> ();
+  ipv4->SetNode (node);
+
+  Ptr<Ipv4L4Demux> ipv4L4Demux = CreateObject<Ipv4L4Demux> ();
+  ipv4L4Demux->SetNode (node);
+
+  AddUdpStack (node, ipv4L4Demux);
+  AddNscStack (node, ipv4L4Demux, soname);
+
+  AddIpv4Impl (node, ipv4);
+  node->AggregateObject (ipv4L4Demux);
+}
+#else
+void
+AddNscInternetStack (Ptr<Node> node, const std::string &soname)
+{
+  NS_ASSERT_MSG(false, "ERROR: ns-3 was compiled without Network Simulation Cradle support");
+}
+#endif
 }//namespace ns3
--- a/src/internet-stack/internet-stack.h	Fri Aug 29 23:08:18 2008 +0200
+++ b/src/internet-stack/internet-stack.h	Fri Aug 29 23:10:00 2008 +0200
@@ -27,6 +27,7 @@
 class Node;
 
 void AddInternetStack (Ptr<Node> node);
+void AddNscInternetStack (Ptr<Node> node, const std::string &soname);
 
 }//namespace ns3
 
--- a/src/internet-stack/wscript	Fri Aug 29 23:08:18 2008 +0200
+++ b/src/internet-stack/wscript	Fri Aug 29 23:10:00 2008 +0200
@@ -1,4 +1,61 @@
 ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+import Params
+import os
+
+# Mercurial repository of the network simulation cradle
+NETWORK_SIMULATION_CRADLE_REPO = "https://secure.wand.net.nz/mercurial/nsc"
+def nsc_fetch():
+    def nsc_clone():
+        print "Retrieving nsc from " + NETWORK_SIMULATION_CRADLE_REPO
+        if os.system("hg version > /dev/null 2>&1") != 0:
+            Params.fatal("Mercurial not installed, http fallback not yet implemented")
+        if os.system("hg -q clone " + NETWORK_SIMULATION_CRADLE_REPO) != 0:
+            Params.fatal("hg -q clone %s failed" % NETWORK_SIMULATION_CRADLE_REPO)
+
+    def nsc_update():
+        if os.system("hg version > /dev/null 2>&1") != 0:
+            Params.warning("Mercurial not installed, not updating nsc source")
+
+        print "Pulling nsc updates from " + NETWORK_SIMULATION_CRADLE_REPO
+        if os.system("cd nsc && hg -q pull %s && hg -q update" % NETWORK_SIMULATION_CRADLE_REPO) != 0:
+            Params.warning("Updating nsc using mercurial failed")
+
+    if not os.path.exists("nsc"):
+        nsc_clone()
+    else:
+        nsc_update()
+
+def configure(conf):
+    # checks for flex and bison, which is needed to build NSCs globaliser
+    def check_nsc_buildutils():
+        import flex
+        import bison
+        conf.check_tool('flex bison')
+        e = conf.create_library_configurator()
+        e.mandatory = True
+        e.name = 'fl'
+        e.run()
+
+    if not Params.g_options.nsc:
+	return
+
+    check_nsc_buildutils()
+
+    arch = os.uname()[4]
+    ok = False
+    if arch == 'x86_64' or arch == 'i686' or arch == 'i586' or arch == 'i486' or arch == 'i386':
+        conf.env['NSC_ENABLED'] = 'yes'
+        conf.define('NETWORK_SIMULATION_CRADLE', 1)
+        conf.write_config_header('ns3/core-config.h')
+        e = conf.create_library_configurator()
+        e.mandatory = True
+        e.name = 'dl'
+        e.define = 'HAVE_DL'
+        e.uselib = 'DL'
+        e.run()
+        ok = True
+    conf.check_message('NSC supported architecture', arch, ok)
+    nsc_fetch()
 
 
 def build(bld):
@@ -43,3 +100,9 @@
         'ipv4-l3-protocol.h',
         'ipv4-static-routing.h',
         ]
+
+    if bld.env()['NSC_ENABLED']:
+        obj.source.append ('nsc-tcp-socket-impl.cc')
+        obj.source.append ('nsc-tcp-l4-protocol.cc')
+        obj.source.append ('nsc-tcp-socket-factory-impl.cc')
+        obj.source.append ('nsc-sysctl.cc')
--- a/src/wscript	Fri Aug 29 23:08:18 2008 +0200
+++ b/src/wscript	Fri Aug 29 23:10:00 2008 +0200
@@ -49,6 +49,7 @@
     conf.sub_config('core')
     conf.sub_config('simulator')
     conf.sub_config('contrib')
+    conf.sub_config('internet-stack')
 
     blddir = os.path.abspath(os.path.join(conf.m_blddir, conf.env.variant()))
     conf.env.append_value('NS3_MODULE_PATH', blddir)
--- a/wscript	Fri Aug 29 23:08:18 2008 +0200
+++ b/wscript	Fri Aug 29 23:10:00 2008 +0200
@@ -55,6 +55,8 @@
 #
 TRACEBALL_SUFFIX = ".tar.bz2"
 
+# directory that contains network simulation cradle source
+NSC_DIR = "nsc"
 
 def dist_hook():
     import tarfile
@@ -165,6 +167,10 @@
                    help=('For regression testing, only run/generate the indicated regression tests, '
                          'specified as a comma separated list of test names'),
                    dest='regression_tests', type="string")
+    opt.add_option('--nsc',
+                   help=('Enable Network Simulation Cradle to allow the use real-world network stacks'),
+                   action="store_true", default=False,
+                   dest='nsc')
 
     # options provided in a script in a subdirectory named "src"
     opt.sub_options('src')
@@ -193,6 +199,7 @@
     
 
 def configure(conf):
+    conf.env['NS3_BUILDDIR'] = conf.m_blddir
     conf.check_tool('compiler_cxx')
 
     # create the second environment, set the variant and set its name
@@ -304,6 +311,28 @@
     return stat >> 8
 
 
+def nsc_build(bld):
+    # XXX: Detect gcc major version(s) available to build supported stacks
+    kernels = [['linux-2.6.18', 'linux2.6.18'],
+               ['linux-2.6.26', 'linux2.6.26']]
+    for dir,name in kernels:
+        soname = 'lib' + name + '.so'
+        tmp = NSC_DIR + '/' + dir +'/' + soname
+        if not os.path.exists(tmp):
+            if os.system('cd ' + NSC_DIR + ' && python scons.py ' + dir) != 0:
+                Params.fatal("Building NSC stack failed")
+        builddir = os.path.abspath(os.path.join(bld.env()['NS3_BUILDDIR'], bld.env ().variant()))
+        if not os.path.exists(builddir + '/nsc'):
+            try:
+                os.symlink('../../' + NSC_DIR, builddir + '/nsc')
+            except:
+                Params.fatal("Error linkink " + builddir + '/nsc')
+        if not os.path.exists(builddir + '/' + soname):
+            try:
+                os.symlink('../../' + NSC_DIR + '/' + dir + '/' + soname, builddir +  '/' + soname)
+            except:
+                Params.fatal("Error linking " + builddir + '/' + soname)
+
 def build(bld):
     if Params.g_options.no_task_lines:
         import Runner
@@ -393,6 +422,9 @@
 
     bld.add_subdirs('bindings/python')
 
+    if env['NSC_ENABLED'] == 'yes':
+        nsc_build(bld)
+
 def get_command_template():
     if Params.g_options.valgrind:
         if Params.g_options.command_template: