branch merge
authorCraig Dowell <craigdo@ee.washington.edu>
Tue, 03 Feb 2009 10:40:16 -0800
changeset 4181 c7c44a32a7c5
parent 4180 1ec09ce94019 (current diff)
parent 4135 3e819441bc75 (diff)
child 4182 d335731bf41f
branch merge
--- a/bindings/python/ns3/__init__.py	Tue Feb 03 09:32:24 2009 -0800
+++ b/bindings/python/ns3/__init__.py	Tue Feb 03 10:40:16 2009 -0800
@@ -1,4 +1,7 @@
 
 from _ns3 import *
 
+import atexit
+atexit.register(Simulator.Destroy)
+del atexit
 
--- a/doc/manual/Makefile	Tue Feb 03 09:32:24 2009 -0800
+++ b/doc/manual/Makefile	Tue Feb 03 10:40:16 2009 -0800
@@ -7,6 +7,7 @@
 SPLIT = --split section
 
 FIGURES = figures
+DOC_FIGURES = ..
 VPATH = $(FIGURES)
 
 IMAGES_EPS = \
@@ -18,7 +19,8 @@
 	$(FIGURES)/sockets-overview.eps \
 	$(FIGURES)/testbed.eps \
 	$(FIGURES)/emulated-channel.eps \
-	$(FIGURES)/snir.eps
+	$(FIGURES)/snir.eps \
+	$(DOC_FIGURES)/WifiArchitecture.eps
 
 IMAGES_PNG = ${IMAGES_EPS:.eps=.png}
 IMAGES_PDF = ${IMAGES_EPS:.eps=.pdf}
@@ -31,6 +33,7 @@
 	callbacks.texi \
 	csma.texi \
 	emulation.texi \
+	new-models.texi \
 	node.texi \
 	objects.texi \
 	other.texi \
--- a/doc/manual/manual.texi	Tue Feb 03 09:32:24 2009 -0800
+++ b/doc/manual/manual.texi	Tue Feb 03 10:40:16 2009 -0800
@@ -92,6 +92,7 @@
 * Wifi NetDevice::
 * CSMA NetDevice::
 * PointToPoint NetDevice::
+* Creating a new ns-3 model::
 * Troubleshooting::
 @end menu
 
@@ -111,6 +112,7 @@
 @include csma.texi
 @include point-to-point.texi
 @c @include other.texi
+@include new-models.texi
 @include troubleshoot.texi
 
 @printindex cp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/manual/new-models.texi	Tue Feb 03 10:40:16 2009 -0800
@@ -0,0 +1,578 @@
+@node Creating a new ns-3 model
+@chapter Creating a new ns-3 model 
+
+This chapter walks through the design process of an @command{ns-3} model.
+In many research cases, users will not be satisfied to merely adapt
+existing models, but may want to extend the core of the simulator in
+a novel way.  We will use the example of adding an ErrorModel to
+a simple @command{ns-3} link as a motivating example of how one might
+approach this problem and proceed through a design and implementation.
+
+@node Design-approach
+@section Design-approach
+
+Consider how you want it to work; what should it do.  Think about these
+things:
+@itemize @bullet
+@item @emph{functionality:}  What functionality should it have?  What
+attributes or configuration is exposed to the user?
+@item @emph{reusability:}  How much should others be able to reuse my design?  
+Can I reuse code from ns-2 to get started?  How does a user integrate
+the model with the rest of another simulation?
+@item @emph{dependencies:}  How can I reduce the introduction of 
+outside dependencies on my new code as much as possible (to make it 
+more modular)?  For instance, should I avoid any dependence on IPv4 if
+I want it to also be used by IPv6?  Should I avoid any dependency
+on IP at all?
+@end itemize
+
+Do not be hesitant to contact the ns-3-users or ns-developers list if 
+you have questions.  In particular, it is important to think about
+the public API of your new model and ask for feedback.  It also helps
+to let others know of your work in case you are interested in 
+collaborators.  
+
+@subsection Example:  ErrorModel
+
+An error model exists in ns-2.  It allows packets to be passed to
+a stateful object that determines, based on a random
+variable, whether the packet is corrupted.  The caller can then
+decide what to do with the packet (drop it, etc.).
+
+The main API of the error model is a function to pass a packet
+to, and the return value of this function is a boolean that
+tells the caller whether any corruption occurred.  Note that
+depending on the error model, the packet data buffer may or may
+not be corrupted.  Let's call this function "IsCorrupt()".
+
+So far, in our design, we have:
+@verbatim
+class ErrorModel
+{
+public:
+ /**
+  * \returns true if the Packet is to be considered as errored/corrupted
+  * \param pkt Packet to apply error model to
+  */
+  bool IsCorrupt (Ptr<Packet> pkt);
+};
+@end verbatim
+Note that we do not pass a const pointer, thereby allowing the function
+to modify the packet if IsCorrupt() returns true.  Not all error models
+will actually modify the packet; whether or not the packet data
+buffer is corrupted should be documented.
+
+We may also want specialized versions of this, such as in ns-2, so
+although it is not the only design choice for polymorphism, we assume
+that we will subclass a base class ErrorModel for specialized classes,
+such as RateErrorModel, ListErrorModel, etc, such as is done in ns-2.
+
+You may be thinking at this point, "Why not make IsCorrupt() a virtual
+method?".  That is one approach; the other is to make the public
+non-virtual function indirect through a private virtual function
+(this in C++ is known as the non virtual interface idiom and is 
+adopted in the ns-3 ErrorModel class).  
+
+Next, should this device have any dependencies on IP or other protocols?
+We do not want to create dependencies on Internet protocols (the error
+model should be applicable to non-Internet protocols too), so we'll keep
+that in mind later.
+
+Another consideration is how objects will include this error model.
+We envision putting an explicit setter in certain NetDevice implementations,
+for example.
+@verbatim
+  /**
+   * Attach a receive ErrorModel to the PointToPointNetDevice.
+   *
+   * The PointToPointNetDevice may optionally include an ErrorModel in
+   * the packet receive chain.
+   *
+   * @see ErrorModel
+   * @param em Ptr to the ErrorModel.
+   */
+  void PointToPointNetDevice::SetReceiveErrorModel(Ptr<ErrorModel> em);
+@end verbatim
+Again, this is not the only choice we have (error models could be aggregated
+to lots of other objects), but it satisfies our primary use case, which
+is to allow a user to force errors on otherwise successful packet
+transmissions, at the NetDevice level.
+
+After some thinking and looking at existing ns-2 code, here is a sample
+API of a base class and first subclass that could be posted for initial 
+review:
+@verbatim
+class ErrorModel 
+{
+public:
+  ErrorModel ();
+  virtual ~ErrorModel ();
+  bool IsCorrupt (Ptr<Packet> pkt);
+  void Reset (void);
+  void Enable (void);
+  void Disable (void);
+  bool IsEnabled (void) const;
+private:
+  virtual bool DoCorrupt (Ptr<Packet> pkt) = 0;
+  virtual void DoReset (void) = 0;
+};
+
+enum ErrorUnit
+  {
+    EU_BIT,
+    EU_BYTE,
+    EU_PKT
+  };
+
+// Determine which packets are errored corresponding to an underlying
+// random variable distribution, an error rate, and unit for the rate.
+class RateErrorModel : public ErrorModel
+{
+public:
+  RateErrorModel ();
+  virtual ~RateErrorModel ();
+  enum ErrorUnit GetUnit (void) const;
+  void SetUnit (enum ErrorUnit error_unit);
+  double GetRate (void) const;
+  void SetRate (double rate);
+  void SetRandomVariable (const RandomVariable &ranvar);
+private:
+  virtual bool DoCorrupt (Ptr<Packet> pkt);
+  virtual void DoReset (void);
+};
+@end verbatim
+
+@node Scaffolding
+@section Scaffolding
+
+Let's say that you are ready to start implementing; you have a fairly clear
+picture of what you want to build, and you may have solicited some
+initial review or suggestions from the list.
+One way to approach the next step (implementation) is to create scaffolding
+and fill in the details as the design matures.  
+
+This section walks through many of the steps you should consider to
+define scaffolding, or a non-functional skeleton of what your model
+will eventually implement.  It is usually good practice to not wait
+to get these details integrated at the end, but instead to plumb a
+skeleton of your model into the system early and then add functions
+later once the API and integration seems about right.  
+
+Note that you will want to modify a few things in the below presentation
+for your model since if you follow the error model verbatim, the code
+you produce will collide with the existing error model.  The below is
+just an outline of how ErrorModel was built that you can adapt to
+other models.
+
+@subsection Review the ns-3 coding style document
+
+At this point, you may want to pause and read the ns-3 coding
+style document, especially if you are considering to contribute your
+code back to the project.  The coding style document is linked off
+the main project page:
+@uref{http://www.nsnam.org/codingstyle.html,,ns-3 coding style}.
+
+@subsection  Decide where in the source tree the model will reside in
+
+All of the ns-3 model source code is in the directory @code{src/}.  
+You will need to choose which subdirectory it resides in.  If it is
+new model code of some sort, it makes sense to put it into the 
+@code{src/} directory somewhere, particularly for ease of integrating
+with the build system.
+
+In the case of the error model, it is very related to the packet 
+class, so it makes sense to implement this in the @code{src/common/}
+directory where ns-3 packets are implemented.  
+
+@subsection  waf and wscript
+
+ns-3 uses the @uref{http://www.freehackers.org/~tnagy/waf.html,,Waf} 
+build system.  You will want to integrate your new
+ns-3 uses the Waf build system.  You will want to integrate your new
+source files into this system.  This requires that you add your files
+to the @code{wscript} file found in each directory.  
+
+Let's start with empty files error-model.h and error-model.cc, and
+add this to @code{src/common/wscript}.  It is really just a matter
+of adding the .cc file to the rest of the source files, and the .h
+file to the list of the header files. 
+
+Now, pop up to the top level directory and type "./waf check".  You
+shouldn't have broken anything by this operation.
+@subsection include guards
+Next, let's add some 
+@uref{http://en.wikipedia.org/wiki/Include_guard,,include guards} in our 
+header file.
+@verbatim
+#ifndef ERROR_MODEL_H
+#define ERROR_MODEL_H
+...
+#endif
+@end verbatim
+
+@subsection namespace ns3
+ns-3 uses the ns3 @uref{http://en.wikipedia.org/wiki/Namespace_(computer_science)#Use_in_common_languages,,namespace}
+to isolate its symbols from other namespaces.
+Typically, a user will next put an ns-3 namespace block in both the cc and
+h file. 
+@verbatim
+namespace ns3 {
+...
+}
+@end verbatim
+
+At this point, we have some skeletal files in which we can start defining
+our new classes.  The header file looks like this:
+
+@verbatim
+#ifndef ERROR_MODEL_H
+#define ERROR_MODEL_H
+
+namespace ns3 {
+
+} // namespace ns3
+#endif
+@end verbatim
+while the @code{error-model.cc} file simply looks like this:
+@verbatim
+#include "error-model.h"
+
+namespace ns3 {
+
+} // namespace ns3
+@end verbatim
+These files should compile since they don't really have any contents.  
+We're now ready to start adding classes.
+
+@node Initial Implementation
+@section Initial Implementation
+
+At this point, we're still working on some scaffolding, but we can
+begin to define our classes, with the functionality to be added later.
+
+@subsection use of class Object?
+
+This is an important design step; whether to use @code{class Object} as 
+a base class for your new classes.
+
+As described in the chapter on the ns-3 @ref{Object model}, classes that 
+inherit from @code{class Object} get special properties:
+@itemize @bullet
+@item the ns-3 type and attribute system (see @ref{Attributes})
+@item an object aggregation system
+@item a smart-pointer reference counting system (class Ptr)
+@end itemize
+
+Classes that derive from @code{class ObjectBase} get the first two
+properties above, but do not get smart pointers.  Classes that
+derive from @code{class RefCountBase} get only the smart-pointer
+reference counting system.
+
+In practice, @code{class Object} is the variant of the three above that
+the ns-3 developer will most commonly encounter.
+
+In our case, we want to make use of the attribute system, and we
+will be passing instances of this object across the ns-3 public API,
+so @code{class Object} is appropriate for us.
+
+@subsection initial classes
+
+One way to proceed is to start by defining the bare minimum functions
+and see if they will compile.  Let's review what all is needed to 
+implement when we derive from class Object.
+
+@verbatim
+#ifndef ERROR_MODEL_H
+#define ERROR_MODEL_H
+
+#include "ns3/object.h"
+
+namespace ns3 {
+  
+class ErrorModel : public Object
+{
+public:
+  static TypeId GetTypeId (void);
+
+  ErrorModel ();
+  virtual ~ErrorModel ();
+};
+
+class RateErrorModel : public ErrorModel
+{
+public:
+  static TypeId GetTypeId (void);
+ 
+  RateErrorModel ();
+  virtual ~RateErrorModel ();
+};
+#endif
+@end verbatim
+
+A few things to note here.  We need to include @code{object.h}.  The
+convention in ns-3 is that if the header file is co-located in the
+same directory, it may be included without any path prefix.  Therefore,
+if we were implementing ErrorModel in @code{src/core} directory, we could
+have just said "@code{#include "object.h"}".  But we are in @code{src/common},
+so we must include it as "@code{#include "ns3/object.h"}".  Note also
+that this goes outside the namespace declaration.
+ 
+Second, each class must implement a static public member function
+called @code{GetTypeId (void)}.  
+
+Third, it is a good idea to implement constructors and destructors rather
+than to let the compiler generate them, and to make the destructor virtual.
+In C++, note also that copy assignment operator and copy constructors
+are auto-generated if they are not defined, so if you do not want those,
+you should implement those as private members.  This aspect of C++ is 
+discussed in Scott Meyers' Effective C++ book. item 45. 
+
+Let's now look at some corresponding skeletal implementation code in the .cc 
+file.
+
+@verbatim
+#include "error-model.h"
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (ErrorModel);
+
+TypeId ErrorModel::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::ErrorModel")
+    .SetParent<Object> ()
+    ;
+  return tid;
+}
+
+ErrorModel::ErrorModel ()
+{ 
+}
+
+ErrorModel::~ErrorModel ()
+{ 
+}
+
+NS_OBJECT_ENSURE_REGISTERED (RateErrorModel);
+
+TypeId RateErrorModel::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::RateErrorModel")
+    .SetParent<ErrorModel> ()
+    .AddConstructor<RateErrorModel> ()
+    ;
+  return tid;
+}
+
+RateErrorModel::RateErrorModel ()
+{
+} 
+
+RateErrorModel::~RateErrorModel ()
+{
+}
+@end verbatim
+
+What is the @code{GetTypeId (void)} function?  This function does a few
+things.  It registers a unique string into the TypeId system.  It establishes  
+the hierarchy of objects in the attribute system (via @code{SetParent}).
+It also declares that certain objects can be created via the object
+creation framework (@code{AddConstructor}).  
+
+The macro @code{NS_OBJECT_ENSURE_REGISTERED (classname)} is needed also
+once for every class that defines a new GetTypeId method, and it does
+the actual registration of the class into the system.
+The @ref{Object model} chapter discusses this in more detail.
+
+@subsection how to include files from elsewhere
+@subsection log component 
+
+Here, write a bit about adding ns-3 logging macros.  Note that
+LOG_COMPONENT_DEFINE is done outside the namespace ns3
+
+@subsection constructor, empty function prototypes
+
+@subsection key variables (default values, attributes)
+
+@subsection test program 1
+
+
+
+@subsection Object Framework
+
+  static const ClassId cid;
+
+
+const InterfaceId ErrorModel::iid =
+  MakeInterfaceId ("ErrorModel", Object::iid);
+
+const ClassId ErrorModel::cid =
+  MakeClassId<ErrorModel> ("ErrorModel", ErrorModel::iid);
+@end verbatim
+
+
+@node Adding-a-sample-script
+@section Adding a sample script
+
+At this point, one may want to try to take the basic scaffolding
+defined above and add it into the system.  Performing this step
+now allows one to use a simpler model when plumbing into the system
+and may also reveal whether any design or API modifications need to be
+made.  Once this is done, we will return to building out the functionality
+of the ErrorModels themselves.
+
+@subsection Add basic support in the class
+
+@verbatim
+point-to-point-net-device.h
+  class ErrorModel;
+  
+  /**
+   * Error model for receive packet events
+   */
+  Ptr<ErrorModel> m_receiveErrorModel;
+  
+@end verbatim
+
+@subsection Add Accessor
+
+@verbatim
+
+  void
+PointToPointNetDevice::SetReceiveErrorModel (Ptr<ErrorModel> em)
+{
+  NS_LOG_FUNCTION (this << em);
+  m_receiveErrorModel = em;
+} 
+
+   .AddAttribute ("ReceiveErrorModel",
+                   "The receiver error model used to simulate packet loss",
+                   PointerValue (),
+                   MakePointerAccessor (&PointToPointNetDevice::m_receiveErrorModel),
+                   MakePointerChecker<ErrorModel> ())
+@end verbatim
+
+@subsection Plumb into the system
+
+@verbatim
+void PointToPointNetDevice::Receive (Ptr<Packet> packet)
+{
+  NS_LOG_FUNCTION (this << packet);
+  uint16_t protocol = 0;
+  
+  if (m_receiveErrorModel && m_receiveErrorModel->IsCorrupt (packet) )
+    {
+//  
+// If we have an error model and it indicates that it is time to lose a
+// corrupted packet, don't forward this packet up, let it go. 
+// 
+      m_dropTrace (packet);
+    } 
+  else
+    {
+//  
+// Hit the receive trace hook, strip off the point-to-point protocol header
+// and forward this packet up the protocol stack.
+//     
+      m_rxTrace (packet);
+      ProcessHeader(packet, protocol);
+      m_rxCallback (this, packet, protocol, GetRemote ());
+      if (!m_promiscCallback.IsNull ())
+        {           m_promiscCallback (this, packet, protocol, GetRemote (), GetAddress (), NetDevice::PACKET_HOST);
+        }
+    }
+}
+@end verbatim
+
+@subsection Create null functional script
+
+@verbatim
+simple-error-model.cc
+
+  // Error model
+  // We want to add an error model to node 3's NetDevice
+  // We can obtain a handle to the NetDevice via the channel and node
+  // pointers
+  Ptr<PointToPointNetDevice> nd3 = PointToPointTopology::GetNetDevice
+    (n3, channel2);
+  Ptr<ErrorModel> em = Create<ErrorModel> ();
+  nd3->SetReceiveErrorModel (em);
+
+
+bool
+ErrorModel::DoCorrupt (Packet& p)
+{
+  NS_LOG_FUNCTION;
+  NS_LOG_UNCOND("Corrupt!");
+  return false;
+}
+@end verbatim
+
+At this point, we can run the program with our trivial ErrorModel
+plumbed into the receive path of the PointToPointNetDevice.  It
+prints out the string "Corrupt!" for each packet received at
+node n3.  Next, we return to the error model to add in a subclass
+that performs more interesting error modeling.
+
+@section Add subclass
+
+The trivial base class ErrorModel does not do anything interesting,
+but it provides a useful base class interface (Corrupt () and Reset ()),
+forwarded to virtual functions that can be subclassed.  Let's next
+consider what we call a BasicErrorModel which is based on the
+ns-2 ErrorModel class (in ns-2/queue/errmodel.@{cc,h@}).
+
+What properties do we want this to have, from a user interface
+perspective?  We would like for the user to be able to trivially
+swap out the type of ErrorModel used in the NetDevice.  We would also
+like the capability to set configurable parameters.
+
+Here are a few simple requirements we will consider:
+@itemize @bullet
+@item Ability to set the random variable that governs the losses
+(default is UniformVariable)
+@item Ability to set the unit (bit, byte, packet, time) of granularity
+over which errors are applied.
+@item Ability to set the rate of errors (e.g. 10^-3) corresponding to
+the above unit of granularity.
+@item Ability to enable/disable (default is enabled)
+@end itemize
+
+@subsection How to subclass
+
+We declare BasicErrorModel to be a subclass of ErrorModel as follows,
+
+@verbatim
+class BasicErrorModel : public ErrorModel
+{
+public:
+  static TypeId GetTypeId (void);
+  ...
+private:
+  // Implement base class pure virtual functions
+  virtual bool DoCorrupt (Ptr<Packet> p);
+  virtual bool DoReset (void);
+  ...
+}
+@end verbatim
+
+and configure the subclass GetTypeId function by setting a unique
+TypeId string and setting the Parent to ErrorModel:
+
+@verbatim
+TypeId RateErrorModel::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::RateErrorModel")
+    .SetParent<ErrorModel> ()
+    .AddConstructor<RateErrorModel> ()
+  ...
+@end verbatim
+
+@node Build-core-functions-and-unit-tests
+@section Build core functions and unit tests
+
+@subsection assert macros
+
+@subsection Writing unit tests
+
+
--- a/doc/manual/wifi.texi	Tue Feb 03 09:32:24 2009 -0800
+++ b/doc/manual/wifi.texi	Tue Feb 03 10:40:16 2009 -0800
@@ -83,6 +83,11 @@
 The source code for the Wifi NetDevice lives in the directory
 @code{src/devices/wifi}.
 
+@float Figure,fig:WifiArchitecture
+@caption{Wifi NetDevice architecture.}
+@image{../WifiArchitecture,5in}
+@end float
+
 @node Using the WifiNetDevice
 @section Using the WifiNetDevice
 
--- a/regression.py	Tue Feb 03 09:32:24 2009 -0800
+++ b/regression.py	Tue Feb 03 10:40:16 2009 -0800
@@ -84,7 +84,7 @@
             program = getattr(mod, "program", short_name)
 
         if hasattr(mod, 'may_run'):
-            reason_cannot_run = mod.may_run(self.env)
+            reason_cannot_run = mod.may_run(self.env, Options.options)
         else:
             reason_cannot_run = None
         if reason_cannot_run:
@@ -122,11 +122,19 @@
         if is_pyscript:
             script = os.path.abspath(os.path.join('..', *os.path.split(program)))
             argv = [self.env['PYTHON'], script] + arguments
-            wutils.run_argv(argv, cwd=trace_output_path)
+            try:
+                wutils.run_argv(argv, cwd=trace_output_path)
+            except Utils.WafError, ex:
+                print >> sys.stderr, ex
+                return 1
         else:
-            wutils.run_program(program,
-                               command_template=wutils.get_command_template(self.env, arguments),
-                               cwd=trace_output_path)
+            try:
+                wutils.run_program(program,
+                                   command_template=wutils.get_command_template(self.env, arguments),
+                                   cwd=trace_output_path)
+            except Utils.WafError, ex:
+                print >> sys.stderr, ex
+                return 1
 
         if Options.options.verbose:
             #diffCmd = "diff traces " + refTestDirName + " | head"
@@ -154,11 +162,19 @@
         if is_pyscript:
             script = os.path.abspath(os.path.join('..', *os.path.split(program)))
             argv = [self.env['PYTHON'], script] + arguments
-            retval = wutils.run_argv(argv, cwd=trace_output_path)
+            try:
+                retval = wutils.run_argv(argv, cwd=trace_output_path)
+            except Utils.WafError, ex:
+                print >> sys.stderr, ex
+                return 1
         else:
-            retval = wutils.run_program(program,
-                                        command_template=wutils.get_command_template(self.env, arguments),
-                                        cwd=trace_output_path)
+            try:
+                retval = wutils.run_program(program,
+                                            command_template=wutils.get_command_template(self.env, arguments),
+                                            cwd=trace_output_path)
+            except Utils.WafError, ex:
+                print >> sys.stderr, ex
+                return 1
         return retval
 
 
--- a/regression/tests/test-csma-bridge.py	Tue Feb 03 09:32:24 2009 -0800
+++ b/regression/tests/test-csma-bridge.py	Tue Feb 03 10:40:16 2009 -0800
@@ -4,7 +4,7 @@
 
 import os.path
 
-def may_run(env):
+def may_run(env, options):
     """Returns 0 when it can run, return non-zero or string (reason) when it cannot run"""
     if env['ENABLE_PYTHON_BINDINGS']:
         return 0
--- a/regression/tests/test-realtime-udp-echo.py	Tue Feb 03 09:32:24 2009 -0800
+++ b/regression/tests/test-realtime-udp-echo.py	Tue Feb 03 10:40:16 2009 -0800
@@ -2,3 +2,6 @@
 
 """Generic trace-comparison-type regression test."""
 
+def may_run(env, options):
+    if not env["ENABLE_REAL_TIME"]:
+        return "Real-time support not available"
--- a/regression/tests/test-tcp-nsc-lfn.py	Tue Feb 03 09:32:24 2009 -0800
+++ b/regression/tests/test-tcp-nsc-lfn.py	Tue Feb 03 10:40:16 2009 -0800
@@ -3,12 +3,16 @@
 """Trace-comparison-type regression test for the Network Simulation Cradle."""
 
 import platform
-
+import sys
 
-def may_run(env):
+def may_run(env, options):
     if not env['NSC_ENABLED']:
         return "NSC not available"
     else:
+        if options.valgrind:
+            return "NSC does not get along with valgrind"
+        if sys.platform != 'linux2':
+            return "NSC is not well supported on non-Linux platforms"
         return 0
 
 
Binary file waf has changed