From 0583ab3bc827e70f3026b26702673cfb3538c490 Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Mon, 16 Jul 2007 21:41:19 -0700 Subject: [PATCH 1/7] changes for 3.0.4 release --- RELEASE_NOTES | 8 ++ SConstruct | 2 - VERSION | 2 +- doc/build.txt | 238 +++++++++++++++++--------------------------------- 4 files changed, 88 insertions(+), 162 deletions(-) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index ae53a615f..9de1ba7c1 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -3,6 +3,14 @@ This file contains ns-3 release notes (most recent releases first). +Release 3.0.4 (2007/07/15) +======================== + + - Enable waf as the default build system. + - Per-packet metadata: a system to track which headers and trailers + are added to a packet + - Simplifications to point-to-point devices and channel + Release 3.0.3 (2007/06/15) ======================== diff --git a/SConstruct b/SConstruct index eb287a041..6d2a8c0b9 100644 --- a/SConstruct +++ b/SConstruct @@ -24,7 +24,6 @@ ns3.add_extra_dist ('RELEASE_NOTES') ns3.add_extra_dist ('AUTHORS') ns3.add_extra_dist ('VERSION') -ns3.add_extra_dist('doc/build-waf.txt') ns3.add_extra_dist('ns3/_placeholder_') for wscript in [ "src/core/wscript", @@ -41,7 +40,6 @@ for wscript in [ "wscript", ]: ns3.add_extra_dist(wscript) -ns3.add_extra_dist('waf') ns3.add_extra_dist('waf.bat') diff --git a/VERSION b/VERSION index 75a22a26a..b0f2dcb32 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.0.3 +3.0.4 diff --git a/doc/build.txt b/doc/build.txt index e724529d3..1e2f45cd3 100644 --- a/doc/build.txt +++ b/doc/build.txt @@ -1,186 +1,106 @@ -If you want to build ns3, you need to install scons (see -http://www.scons.org). scons takes care of building -the whole source tree using your system compiler. scons -0.91.1 and 0.91.96 have been tested and are known to -work on linux FC5, Mac os X and MinGW. +The Waf build system is used to build ns-3. Waf is a Python-based +build system (http://www.freehackers.org/~tnagy/waf.html) -To start a build, you can just type 'scons' which -will generate a debug shared build by default, located -in the directory 'build-dir/dbg-shared/bin' and -'build-dir/dbg-shared/lib'. +=== Installing Waf === -All builds are built with debugging symbols. Debugging -builds enable asserts while optimized builds disable them. -On platforms which support it, rpath is used which means that -the executable binaries generated link explicitely against -the right libraries. This saves you the pain of having to -setup environment variables to point to the right libraries. +If this file is part of a development release tarball, the top-level +ns-3 directory should contain a current waf script. -(Note: An alternative build system (Waf) is being -evaluated in the development branch of ns-3-dev on our server -only (i.e., not in the release tarballs)-- see doc/build-waf.txt) +However, the ns-3 Mercurial code repository does not contain the waf +script. Instead, developers should check it out from a subversion +repository: -1) Options ----------- + svn checkout http://waf.googlecode.com/svn/tags/ns3/ waf -- verbose: if you have installed scons 0.91.96 or higher, - the default build output is terse. To get a more verbose - output, you need to set the 'verbose' variable to 'y'. -Example: scons verbose=y -- cflags: flags for the C compiler. -Example: scons cflags="-O3 -ffast-math" -- cxxflags: flags for the C++ compiler. -Example: scons cxxflags="-O3 -ffast-math" -- ldflags: flags for the linker: -Example: scons ldflags="-L/foo -L/bar" -- cc: the C compiler to use: -Example: scons cc=gcc-4.0 -- cxx: the C++ compiler to use: -Example: scons cxx=g++-4.0 -- high-precision-as-double: set to 'y' to make sure that the - high-precision arithmetics performed by the Time class on - behalf of the user will use doubles. By default, the code - uses 128 integers. -Example: scons high-precision-as-double=y -- inheritenv: set to 'y' if you want to make your compiler - execute within the same environment (env vars) as your own - shell. This is typically used to make colorgcc work. -Example: scons inheritenv=y +[ note: 'tags/ns3' is a tag that represents the last svn version +tested to work correctly with ns3, although 'trunk' will likely work + as well ] -2) Targets ----------- +Then it can be installed system-wide with 'sudo waf-light install'. +When preparing a distribution, the resulting 'waf' script, which is +self contained (no external files needed), can be easily included in +the tarball so that users downloading ns-3 can easily build it without +having Waf installed (although Python >= 2.3 is still needed). -- doc: build the doxygen documentation. -Example: scons doc +=== Building with Waf === -- dbg-shared: a debug build using shared libraries. - The files are built in 'build-dir/dbg-shared/'. -Example: scons dbg-shared +To build ns-3 with waf type the commands: + 1. waf configure [options] + 2. waf -- dbg-static: a debug build using static libraries - The files are built in 'build-dir/dbg-static/'. -Example: scons dbg-static +To see valid configure options, type waf --help. The most important +option is -d . Valid debug levels (which are listed in +waf --help) are: ultradebug, debug, release, and optimized. It is +also possible to change the flags used for compilation with (e.g.): +CXXFLAGS="-O3" waf configure. -- opt-shared: an optimized build using shared libraries. - The files are built in 'build-dir/opt-shared/'. -Example: scons opt-shared +[ Note: Unlike some other build tools, to change the build target, +the option must be supplied during the configure stage rather than +the build stage (i.e., "waf -d optimized" will not work; instead, do +"waf -d optimized configure; waf" ] -- opt-static: an optimized build using static libraries. - The files are built in 'build-dir/opt-static/'. -Example: scons opt-static +The resulting binaries are placed in build//srcpath. -- dbg: an alias for dbg-shared -Example: scons dbg +Other waf usages include: -- opt: an alias for opt-shared -Example: scons opt + 1. waf check + Runs the unit tests -- all: alias for dbg-shared, dbg-static, opt-shared - and opt-static -Example: scons all + 2. waf --doxygen + Run doxygen to generate documentation -- gcov: code coverage analysis. Build a debugging version of - the code for code coverage analysis in 'build-dir/gcov'. Once - the code has been built, you can run various applications to - exercise the code paths. To generate an html report from - the gcov data, use the lcov-report target + 3. waf --lcov-report + Run code coverage analysis (assuming the project was configured +with --enable-gcov) -- lcov-report: generate html report of gcov data. The output - is stored in 'build-dir/lcov-report/'. + 4. waf --run "program [args]" + Run a ns3 program, given its target name, with the given + arguments. This takes care of automatically modifying the the + path for finding the ns3 dynamic libraries in the environment + before running the program. Note: the "program [args]" string is + parsed using POSIX shell rules. -- dist: generate a release tarball and zipfile from the - source tree. The tarball and zipfile name are generated - according to the version number stored in the SConstruct - file. -Example in SConstruct: -ns3 = Ns3 () -ns3.name = 'foo' -ns3.version = '0.0.10' -Example command: scons dist -Example output files: -foo-0.0.10.tar.gz -foo-0.0.10.zip + 5. waf --shell + Starts a nested system shell with modified environment to run ns3 programs. -- distcheck: generate a release tarball and zipfile and - attempt to run the 'all' target for the release tarball. -Example: scons distcheck + 6. waf distclean + Cleans out the entire build/ directory -3) How the build system works ------------------------------ + 7. waf dist + The command 'waf dist' can be used to create a distribution tarball. + It includes all files in the source directory, except some particular + extensions that are blacklisted, such as back files (ending in ~). -The current build system defines what are called "ns3 modules": each module -is a set of source files, normal header files and installable header -files. Each module also depends on a set of other modules. We build -modules automatically in the correct order. That is, we always start -from the module which does not depend on any other module (core) and -proceed with the other modules and make sure that when a module is -built, all the modules it depends upon have already been built. -To build a module, we: -1) generate the .o files -2) link the .o files together -3) install the installable headers in the common directory -top_build_dir/include/ns3. +=== Extending ns-3 === -This means that if you want to use a header from your own module, you -should just include it: #include "foo.h" but if you want to include a -header from another module, you need to include it with #include -"ns3/bar.h". This allows you to make sure that our "public" ns3 headers -do not conflict with existing system-level headers. For instance, -if you were to define a header called queue.h, you would include -ns3/queue.h rather than queue.h, when including from a separate module, -since many systems provide a queue.h system include file. +To add new modules: + 1. Create the module directory under src (or src/devices, or whatever); + 2. Add the source files to it; + 3. Add a 'wscript' describing it; + 4. Add the module subdirectory name to the all_modules list in src/wscript. -4) How to add files to a module ? ---------------------------------- +A module's wscript file is basically a regular Waf script. A ns-3 +module is created as a cpp/shlib object, like this: -In the main SConstruct file, you can add source code -to the add_sources method. For example, to add a foo.cc -file to the core module, we coud do this: -core.add_sources ('foo.cc') -Of course, if this file implements public API, its -header should be installable: -core.add_inst_headers ('foo.h') +def build(bld): + obj = bld.create_obj('cpp', 'shlib') -5) How to create a new module ? -------------------------------- + ## set module name; by convention it starts with ns3- + obj.name = 'ns3-mymodule' + obj.target = obj.name -# create a new module. First arg is the name of -# the new module. Second arg is the directory in -# which all source files for this module reside. -my_module = build.Ns3Module ('my', 'src/my_dir') -# add it to build system -ns3.add (my_module) -# specify module dependencies. Here, depends -# on the 'ipv4' and 'core' modules -my_module.add_deps (['core', 'ipv4']) -# add source code to build located in -# src/my_dir -my_module.add_sources ([ - 'my_a.cc', - 'my_b.cc', - 'my_c.cc' -]) -my_module.add_sources ([ - 'my_d.cc' -]) -# add headers which are not public -my_module.add_headers ([ - 'my_a.h', - 'my_c.h' -]) -# add headers which are public -my_module.add_inst_headers ([ - 'my_b.h' -]) -my_module.add_inst_headers ([ - 'my_d.h' -]) -# if you need to link against an external library, -# you must add 'external' dependencies. Here, the -# pthread library -my_module.add_external_dep ('pthread') -# by default, a module is conceptually a library. If you -# want to generate an executable from a module you need to: -my_module.set_executable () + ## list dependencies to other modules + obj.uselib_local = ['ns3-core'] + + ## list source files (private or public header files excluded) + obj.source = [ + 'mymodule.cc', + ] + + ## list module public header files + headers = bld.create_obj('ns3header') + headers.source = [ + 'mymodule-header.h', + ] From 2c813805e7ffde268c6a8a74b4cbca8218e4f0b8 Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Mon, 16 Jul 2007 22:43:10 -0700 Subject: [PATCH 2/7] Remove doc/build-waf.txt --- doc/build-waf.txt | 114 ---------------------------------------------- 1 file changed, 114 deletions(-) delete mode 100644 doc/build-waf.txt diff --git a/doc/build-waf.txt b/doc/build-waf.txt deleted file mode 100644 index 42bc70eb1..000000000 --- a/doc/build-waf.txt +++ /dev/null @@ -1,114 +0,0 @@ -The main ns-3 build system is SCons. Read the file build.txt -for SCons instructions. - -Waf is an alternative build system, similar to SCons. ns-3 now is -able to build with Waf, in parallel to SCons. - -(http://www.freehackers.org/~tnagy/waf.html) - -Note: the Waf build scripts are experimental at this stage. -Gustavo Carneiro (gjcarneiro@gmail.com) is the maintainer. - -=== Building with Waf === - -To build ns-3 with waf type the commands: - 1. waf configure [options] - 2. waf - -[ Note: if waf does not exist in your path, see the section -"Note for developers" below ] - -To see valid configure options, type waf --help. The most important -option is -d . Valid debug levels (which are listed in -waf --help) are: ultradebug, debug, release, and optimized. It is -also possible to change the flags used for compilation with (e.g.): -CXXFLAGS="-O3" waf configure. - -[ Note: Unlike some other build tools, to change the build target, -the option must be supplied during the configure stage rather than -the build stage (i.e., "waf -d optimized" will not work; instead, do -"waf -d optimized configure; waf" ] - -The resulting binaries are placed in build//srcpath. - -Other waf usages include: - - 1. waf check - Runs the unit tests - - 2. waf --doxygen - Run doxygen to generate documentation - - 3. waf --lcov-report - Run code coverage analysis (assuming the project was configured -with --enable-gcov) - - 4. waf --run "program [args]" - Run a ns3 program, given its target name, with the given - arguments. This takes care of automatically modifying the the - path for finding the ns3 dynamic libraries in the environment - before running the program. Note: the "program [args]" string is - parsed using POSIX shell rules. - - 5. waf --shell - Starts a nested system shell with modified environment to run ns3 programs. - - 6. waf distclean - Cleans out the entire build/ directory - - 7. waf dist - The command 'waf dist' can be used to create a distribution tarball. - It includes all files in the source directory, except some particular - extensions that are blacklisted, such as back files (ending in ~). - - -=== Extending ns-3 === - -To add new modules: - 1. Create the module directory under src (or src/devices, or whatever); - 2. Add the source files to it; - 3. Add a 'wscript' describing it; - 4. Add the module subdirectory name to the all_modules list in src/wscript. - -A module's wscript file is basically a regular Waf script. A ns-3 -module is created as a cpp/shlib object, like this: - -def build(bld): - obj = bld.create_obj('cpp', 'shlib') - - ## set module name; by convention it starts with ns3- - obj.name = 'ns3-mymodule' - obj.target = obj.name - - ## list dependencies to other modules - obj.uselib_local = ['ns3-core'] - - ## list source files (private or public header files excluded) - obj.source = [ - 'mymodule.cc', - ] - - ## list module public header files - headers = bld.create_obj('ns3header') - headers.source = [ - 'mymodule-header.h', - ] - - -=== Note for developers === - -The ns-3 code repository does not contain the waf script. Instead, -developers should check it out from a subversion repository: - - svn checkout http://waf.googlecode.com/svn/tags/ns3/ waf - -[ note: 'tags/ns3' is a tag that represents the last svn version -tested to work correctly with ns3, although 'trunk' will likely work - as well ] - -Then it can be installed system-wide with 'sudo waf-light install'. -When preparing a distribution, the resulting 'waf' script, which is -self contained (no external files needed), can be easily included in -the tarball so that users downloading ns-3 can easily build it without -having Waf installed (although Python >= 2.3 is still needed). - From 3ec27d06ecfe6400020440efb7cef595de76bd50 Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Mon, 16 Jul 2007 22:44:02 -0700 Subject: [PATCH 3/7] Added tag release ns-3.0.4 for changeset 5701e60bf01a --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 35fb54f89..bff7cf994 100644 --- a/.hgtags +++ b/.hgtags @@ -2,3 +2,4 @@ 7ac5a4b0969b255c4824c926c2b37ef450136ce9 release ns-3.0.2 0dc81e76166c56aaae64da48b673b62155943aad packet-history-working 38099dd26e9467b8f49f8632f22789858149a6e7 release ns-3.0.3 +5701e60bf01a8ac1308945e69001e0cc07948faf release ns-3.0.4 From 52049833fd00c3faf146837befec4686ed3ec7a8 Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Mon, 16 Jul 2007 22:49:48 -0700 Subject: [PATCH 4/7] update release checklist --- doc/release_steps.txt | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/doc/release_steps.txt b/doc/release_steps.txt index e5c17ddfc..689013ce6 100644 --- a/doc/release_steps.txt +++ b/doc/release_steps.txt @@ -5,15 +5,23 @@ Steps in doing an ns-3 release - revise and check in RELEASE_NOTES - update and check in VERSION to the latest release number 2. make a new "architecture.pdf" document and place it in the doc/ directory -3. scons dist -4. test tarball on release platforms (run-tests and simple-p2p) -5. tag ns-3-dev with "release ns-3.0.X" -6. clone the ns-3-dev and place it on the repository -7. upload "ns-3.0.x.tar.gz" to the releases/ directory on the server -8. update web page +3. add current version of waf script from subversion: + - svn checkout http://waf.googlecode.com/svn/tags/ns3/ waf + - build waf script and put it into top of ns-3-dev +4. cd ns-3-dev; ./waf configure; ./waf dist +5. test tarball on release platforms (run-tests and simple-p2p) +6. tag ns-3-dev with "release ns-3.0.X" + - hg tag "release ns-3.0.x" + - hg push +7. clone the tagged ns-3-dev and place it on the repository + - ssh code.nsnam.org; sudo; su code; + - cp -r /home/code/repos/ns-3-dev /home/code/repos/ns-3.0.x + - cd /home/code/repos/ns-3.0.x/.hg and edit the hgrc appropriately +8. upload "ns-3.0.x.tar.bz2" to the releases/ directory on the server +9. update web page - add link to news.html - update download.html - update roadmap.html - build and update Doxygen directory on the server - update and upload software architecture document (PDF, HTML) -9. announce to ns-developers, with summary of release notes +10. announce to ns-developers, with summary of release notes From a694ccb39ee9bd4d23368af180d3d3cb273e9f7a Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Wed, 18 Jul 2007 11:43:39 +0100 Subject: [PATCH 5/7] WAF: add a --command-template option to e.g. allow running programs with valgrind, gdb, etc. --- doc/build.txt | 9 ++++ src/internet-node/arp-cache.cc | 2 + src/internet-node/arp-ipv4-interface.cc | 15 +++++- src/internet-node/arp-l3-protocol.cc | 22 ++++++++ src/internet-node/ipv4-l3-protocol.cc | 49 ++++++++++++------ src/node/ipv4-address.cc | 12 +++++ src/node/ipv4-address.h | 15 +++++- wscript | 68 ++++++++++++++++++------- 8 files changed, 157 insertions(+), 35 deletions(-) diff --git a/doc/build.txt b/doc/build.txt index 1e2f45cd3..bfb2b518d 100644 --- a/doc/build.txt +++ b/doc/build.txt @@ -60,6 +60,15 @@ with --enable-gcov) before running the program. Note: the "program [args]" string is parsed using POSIX shell rules. + 4.1 waf --run programname --command-template "... %s ..." + + Same as --run, but uses a command template with %s replaced by the + actual program (whose name is given by --run). This can be use to + run ns-3 programs with helper tools. For example, to run unit + tests with valgrind, use the command: + + waf --run run-tests --command-template "valgrind %s" + 5. waf --shell Starts a nested system shell with modified environment to run ns3 programs. diff --git a/src/internet-node/arp-cache.cc b/src/internet-node/arp-cache.cc index e9f48561d..92cb13af4 100644 --- a/src/internet-node/arp-cache.cc +++ b/src/internet-node/arp-cache.cc @@ -109,6 +109,8 @@ ArpCache::Lookup (Ipv4Address to) ArpCache::Entry * ArpCache::Add (Ipv4Address to) { + NS_ASSERT (m_arpCache.find (to) == m_arpCache.end ()); + ArpCache::Entry *entry = new ArpCache::Entry (this); m_arpCache[to] = entry; return entry; diff --git a/src/internet-node/arp-ipv4-interface.cc b/src/internet-node/arp-ipv4-interface.cc index 42d6af238..4ca7ebbb3 100644 --- a/src/internet-node/arp-ipv4-interface.cc +++ b/src/internet-node/arp-ipv4-interface.cc @@ -21,6 +21,7 @@ */ #include "ns3/packet.h" +#include "ns3/debug.h" #include "ns3/composite-trace-resolver.h" #include "ns3/node.h" #include "ns3/net-device.h" @@ -60,7 +61,19 @@ ArpIpv4Interface::SendTo (Packet p, Ipv4Address dest) { Ptr arp = m_node->QueryInterface (ArpPrivate::iid); MacAddress hardwareDestination; - bool found = arp->Lookup (p, dest, GetDevice (), &hardwareDestination); + bool found; + + if (dest.IsBroadcast ()) + { + hardwareDestination = GetDevice ()->GetBroadcast (); + found = true; + } + else + { + Ptr arp = m_node->QueryInterface (ArpPrivate::iid); + found = arp->Lookup (p, dest, GetDevice (), &hardwareDestination); + } + if (found) { GetDevice ()->Send (p, hardwareDestination, Ipv4L3Protocol::PROT_NUMBER); diff --git a/src/internet-node/arp-l3-protocol.cc b/src/internet-node/arp-l3-protocol.cc index f04a6aa25..b68995be3 100644 --- a/src/internet-node/arp-l3-protocol.cc +++ b/src/internet-node/arp-l3-protocol.cc @@ -87,6 +87,13 @@ ArpL3Protocol::Receive(Packet& packet, Ptr device) ArpCache *cache = FindCache (device); ArpHeader arp; packet.RemoveHeader (arp); + + NS_DEBUG ("ARP: received "<< (arp.IsRequest ()? "request" : "reply") << + " node="<GetId ()<<", got request from " << + arp.GetSourceIpv4Address () << " for address " << + arp.GetDestinationIpv4Address () << "; we have address " << + cache->GetInterface ()->GetAddress ()); + if (arp.IsRequest () && arp.GetDestinationIpv4Address () == cache->GetInterface ()->GetAddress ()) { @@ -128,6 +135,12 @@ ArpL3Protocol::Receive(Packet& packet, Ptr device) // XXX report packet as dropped. } } + else + { + NS_DEBUG ("node="<GetId ()<<", got request from " << + arp.GetSourceIpv4Address () << " for unknown address " << + arp.GetDestinationIpv4Address () << " -- drop"); + } } bool ArpL3Protocol::Lookup (Packet &packet, Ipv4Address destination, @@ -203,6 +216,11 @@ void ArpL3Protocol::SendArpRequest (ArpCache const *cache, Ipv4Address to) { ArpHeader arp; + NS_DEBUG ("ARP: sending request from node "<GetId ()<< + " || src: " << cache->GetDevice ()->GetAddress () << + " / " << cache->GetInterface ()->GetAddress () << + " || dst: " << cache->GetDevice ()->GetBroadcast () << + " / " << to); arp.SetRequest (cache->GetDevice ()->GetAddress (), cache->GetInterface ()->GetAddress (), cache->GetDevice ()->GetBroadcast (), @@ -216,6 +234,10 @@ void ArpL3Protocol::SendArpReply (ArpCache const *cache, Ipv4Address toIp, MacAddress toMac) { ArpHeader arp; + NS_DEBUG ("ARP: sending reply from node "<GetId ()<< + "|| src: " << cache->GetDevice ()->GetAddress () << + " / " << cache->GetInterface ()->GetAddress () << + " || dst: " << toMac << " / " << toIp); arp.SetReply (cache->GetDevice ()->GetAddress (), cache->GetInterface ()->GetAddress (), toMac, toIp); diff --git a/src/internet-node/ipv4-l3-protocol.cc b/src/internet-node/ipv4-l3-protocol.cc index 4a46290e6..ff3aef6cf 100644 --- a/src/internet-node/ipv4-l3-protocol.cc +++ b/src/internet-node/ipv4-l3-protocol.cc @@ -404,23 +404,40 @@ Ipv4L3Protocol::Send (Packet const &packet, m_identification ++; - // XXX Note here that in most ipv4 stacks in the world, - // the route calculation for an outgoing packet is not - // done in the ip layer. It is done within the application - // socket when the first packet is sent to avoid this - // costly lookup on a per-packet basis. - // That would require us to get the route from the packet, - // most likely with a packet tag. The higher layers do not - // do this yet for us. - Ipv4Route *route = Lookup (ipHeader.GetDestination ()); - if (route == 0) + if (destination.IsBroadcast ()) { - NS_DEBUG ("not for me -- forwarding but no route to host. drop."); - m_dropTrace (packet); - return; - } + uint32_t ifaceIndex = 0; + for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin (); + ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++) + { + Ipv4Interface *outInterface = *ifaceIter; + Packet packetCopy = packet; - SendRealOut (packet, ipHeader, *route); + NS_ASSERT (packetCopy.GetSize () <= outInterface->GetMtu ()); + packetCopy.AddHeader (ipHeader); + m_txTrace (packetCopy, ifaceIndex); + outInterface->Send (packetCopy, destination); + } + } + else + { + // XXX Note here that in most ipv4 stacks in the world, + // the route calculation for an outgoing packet is not + // done in the ip layer. It is done within the application + // socket when the first packet is sent to avoid this + // costly lookup on a per-packet basis. + // That would require us to get the route from the packet, + // most likely with a packet tag. The higher layers do not + // do this yet for us. + Ipv4Route *route = Lookup (ipHeader.GetDestination ()); + if (route == 0) + { + NS_DEBUG ("not for me -- forwarding but no route to host. drop."); + m_dropTrace (packet); + return; + } + SendRealOut (packet, ipHeader, *route); + } } void @@ -470,7 +487,7 @@ Ipv4L3Protocol::Forwarding (Packet const &packet, Ipv4Header &ipHeader, Ptr Date: Wed, 18 Jul 2007 12:17:53 +0100 Subject: [PATCH 6/7] Backed out changeset df68dad55087ea649a33f04e78b4ff4cf324acdd --- doc/build.txt | 9 ---- src/internet-node/arp-cache.cc | 2 - src/internet-node/arp-ipv4-interface.cc | 15 +----- src/internet-node/arp-l3-protocol.cc | 22 -------- src/internet-node/ipv4-l3-protocol.cc | 49 ++++++------------ src/node/ipv4-address.cc | 12 ----- src/node/ipv4-address.h | 15 +----- wscript | 68 +++++++------------------ 8 files changed, 35 insertions(+), 157 deletions(-) diff --git a/doc/build.txt b/doc/build.txt index bfb2b518d..1e2f45cd3 100644 --- a/doc/build.txt +++ b/doc/build.txt @@ -60,15 +60,6 @@ with --enable-gcov) before running the program. Note: the "program [args]" string is parsed using POSIX shell rules. - 4.1 waf --run programname --command-template "... %s ..." - - Same as --run, but uses a command template with %s replaced by the - actual program (whose name is given by --run). This can be use to - run ns-3 programs with helper tools. For example, to run unit - tests with valgrind, use the command: - - waf --run run-tests --command-template "valgrind %s" - 5. waf --shell Starts a nested system shell with modified environment to run ns3 programs. diff --git a/src/internet-node/arp-cache.cc b/src/internet-node/arp-cache.cc index 92cb13af4..e9f48561d 100644 --- a/src/internet-node/arp-cache.cc +++ b/src/internet-node/arp-cache.cc @@ -109,8 +109,6 @@ ArpCache::Lookup (Ipv4Address to) ArpCache::Entry * ArpCache::Add (Ipv4Address to) { - NS_ASSERT (m_arpCache.find (to) == m_arpCache.end ()); - ArpCache::Entry *entry = new ArpCache::Entry (this); m_arpCache[to] = entry; return entry; diff --git a/src/internet-node/arp-ipv4-interface.cc b/src/internet-node/arp-ipv4-interface.cc index 4ca7ebbb3..42d6af238 100644 --- a/src/internet-node/arp-ipv4-interface.cc +++ b/src/internet-node/arp-ipv4-interface.cc @@ -21,7 +21,6 @@ */ #include "ns3/packet.h" -#include "ns3/debug.h" #include "ns3/composite-trace-resolver.h" #include "ns3/node.h" #include "ns3/net-device.h" @@ -61,19 +60,7 @@ ArpIpv4Interface::SendTo (Packet p, Ipv4Address dest) { Ptr arp = m_node->QueryInterface (ArpPrivate::iid); MacAddress hardwareDestination; - bool found; - - if (dest.IsBroadcast ()) - { - hardwareDestination = GetDevice ()->GetBroadcast (); - found = true; - } - else - { - Ptr arp = m_node->QueryInterface (ArpPrivate::iid); - found = arp->Lookup (p, dest, GetDevice (), &hardwareDestination); - } - + bool found = arp->Lookup (p, dest, GetDevice (), &hardwareDestination); if (found) { GetDevice ()->Send (p, hardwareDestination, Ipv4L3Protocol::PROT_NUMBER); diff --git a/src/internet-node/arp-l3-protocol.cc b/src/internet-node/arp-l3-protocol.cc index b68995be3..f04a6aa25 100644 --- a/src/internet-node/arp-l3-protocol.cc +++ b/src/internet-node/arp-l3-protocol.cc @@ -87,13 +87,6 @@ ArpL3Protocol::Receive(Packet& packet, Ptr device) ArpCache *cache = FindCache (device); ArpHeader arp; packet.RemoveHeader (arp); - - NS_DEBUG ("ARP: received "<< (arp.IsRequest ()? "request" : "reply") << - " node="<GetId ()<<", got request from " << - arp.GetSourceIpv4Address () << " for address " << - arp.GetDestinationIpv4Address () << "; we have address " << - cache->GetInterface ()->GetAddress ()); - if (arp.IsRequest () && arp.GetDestinationIpv4Address () == cache->GetInterface ()->GetAddress ()) { @@ -135,12 +128,6 @@ ArpL3Protocol::Receive(Packet& packet, Ptr device) // XXX report packet as dropped. } } - else - { - NS_DEBUG ("node="<GetId ()<<", got request from " << - arp.GetSourceIpv4Address () << " for unknown address " << - arp.GetDestinationIpv4Address () << " -- drop"); - } } bool ArpL3Protocol::Lookup (Packet &packet, Ipv4Address destination, @@ -216,11 +203,6 @@ void ArpL3Protocol::SendArpRequest (ArpCache const *cache, Ipv4Address to) { ArpHeader arp; - NS_DEBUG ("ARP: sending request from node "<GetId ()<< - " || src: " << cache->GetDevice ()->GetAddress () << - " / " << cache->GetInterface ()->GetAddress () << - " || dst: " << cache->GetDevice ()->GetBroadcast () << - " / " << to); arp.SetRequest (cache->GetDevice ()->GetAddress (), cache->GetInterface ()->GetAddress (), cache->GetDevice ()->GetBroadcast (), @@ -234,10 +216,6 @@ void ArpL3Protocol::SendArpReply (ArpCache const *cache, Ipv4Address toIp, MacAddress toMac) { ArpHeader arp; - NS_DEBUG ("ARP: sending reply from node "<GetId ()<< - "|| src: " << cache->GetDevice ()->GetAddress () << - " / " << cache->GetInterface ()->GetAddress () << - " || dst: " << toMac << " / " << toIp); arp.SetReply (cache->GetDevice ()->GetAddress (), cache->GetInterface ()->GetAddress (), toMac, toIp); diff --git a/src/internet-node/ipv4-l3-protocol.cc b/src/internet-node/ipv4-l3-protocol.cc index ff3aef6cf..4a46290e6 100644 --- a/src/internet-node/ipv4-l3-protocol.cc +++ b/src/internet-node/ipv4-l3-protocol.cc @@ -404,40 +404,23 @@ Ipv4L3Protocol::Send (Packet const &packet, m_identification ++; - if (destination.IsBroadcast ()) + // XXX Note here that in most ipv4 stacks in the world, + // the route calculation for an outgoing packet is not + // done in the ip layer. It is done within the application + // socket when the first packet is sent to avoid this + // costly lookup on a per-packet basis. + // That would require us to get the route from the packet, + // most likely with a packet tag. The higher layers do not + // do this yet for us. + Ipv4Route *route = Lookup (ipHeader.GetDestination ()); + if (route == 0) { - uint32_t ifaceIndex = 0; - for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin (); - ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++) - { - Ipv4Interface *outInterface = *ifaceIter; - Packet packetCopy = packet; + NS_DEBUG ("not for me -- forwarding but no route to host. drop."); + m_dropTrace (packet); + return; + } - NS_ASSERT (packetCopy.GetSize () <= outInterface->GetMtu ()); - packetCopy.AddHeader (ipHeader); - m_txTrace (packetCopy, ifaceIndex); - outInterface->Send (packetCopy, destination); - } - } - else - { - // XXX Note here that in most ipv4 stacks in the world, - // the route calculation for an outgoing packet is not - // done in the ip layer. It is done within the application - // socket when the first packet is sent to avoid this - // costly lookup on a per-packet basis. - // That would require us to get the route from the packet, - // most likely with a packet tag. The higher layers do not - // do this yet for us. - Ipv4Route *route = Lookup (ipHeader.GetDestination ()); - if (route == 0) - { - NS_DEBUG ("not for me -- forwarding but no route to host. drop."); - m_dropTrace (packet); - return; - } - SendRealOut (packet, ipHeader, *route); - } + SendRealOut (packet, ipHeader, *route); } void @@ -487,7 +470,7 @@ Ipv4L3Protocol::Forwarding (Packet const &packet, Ipv4Header &ipHeader, Ptr Date: Wed, 18 Jul 2007 12:20:31 +0100 Subject: [PATCH 7/7] WAF: add a --command-template option to e.g. allow running programs with valgrind, gdb, etc. --- doc/build.txt | 9 +++++++ wscript | 68 ++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 60 insertions(+), 17 deletions(-) diff --git a/doc/build.txt b/doc/build.txt index 1e2f45cd3..bfb2b518d 100644 --- a/doc/build.txt +++ b/doc/build.txt @@ -60,6 +60,15 @@ with --enable-gcov) before running the program. Note: the "program [args]" string is parsed using POSIX shell rules. + 4.1 waf --run programname --command-template "... %s ..." + + Same as --run, but uses a command template with %s replaced by the + actual program (whose name is given by --run). This can be use to + run ns-3 programs with helper tools. For example, to run unit + tests with valgrind, use the command: + + waf --run run-tests --command-template "valgrind %s" + 5. waf --shell Starts a nested system shell with modified environment to run ns3 programs. diff --git a/wscript b/wscript index bfa1d96de..35c17074a 100644 --- a/wscript +++ b/wscript @@ -1,5 +1,4 @@ ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- -import os import sys import shlex import shutil @@ -66,8 +65,14 @@ def set_options(opt): dest='doxygen') opt.add_option('--run', - help=('Run a locally built program'), + help=('Run a locally built program; argument can be a program name,' + ' or a command starting with the program name.'), type="string", default='', dest='run') + opt.add_option('--command-template', + help=('Template of the command used to run the program given by --run;' + ' It should be a shell command string containing %s inside,' + ' which will be replaced by the actual program.'), + type="string", default=None, dest='command_template') opt.add_option('--shell', help=('Run a shell with an environment suitably modified to run locally built programs'), @@ -163,7 +168,11 @@ def shutdown(): doxygen() if Params.g_options.run: - run_program(Params.g_options.run) + run_program(Params.g_options.run, Params.g_options.command_template) + raise SystemExit(0) + + if Params.g_options.command_template: + Params.fatal("Option --command-template requires the option --run to be given") def _find_program(program_name, env): launch_dir = os.path.abspath(Params.g_cwd_launch) @@ -212,33 +221,58 @@ def _run_argv(argv): retval = subprocess.Popen(argv, env=os_env).wait() if retval: - raise SystemExit(retval) + Params.fatal("Command %s exited with code %i" % (argv, retval)) -def run_program(program_string): +def run_program(program_string, command_template=None): + """ + if command_template is not None, then program_string == program + name and argv is given by command_template with %s replaced by the + full path to the program. Else, program_string is interpreted as + a shell command with first name being the program name. + """ env = Params.g_build.env_of_name('default') - argv = shlex.split(program_string) - program_name = argv[0] - try: - program_obj = _find_program(program_name, env) - except ValueError, ex: - Params.fatal(str(ex)) + if command_template is None: + argv = shlex.split(program_string) + program_name = argv[0] - try: - program_node, = program_obj.m_linktask.m_outputs - except AttributeError: - Params.fatal("%s does not appear to be a program" % (program_name,)) + try: + program_obj = _find_program(program_name, env) + except ValueError, ex: + Params.fatal(str(ex)) + + try: + program_node, = program_obj.m_linktask.m_outputs + except AttributeError: + Params.fatal("%s does not appear to be a program" % (program_name,)) + + execvec = [program_node.abspath(env)] + argv[1:] + + else: + + program_name = program_string + try: + program_obj = _find_program(program_name, env) + except ValueError, ex: + Params.fatal(str(ex)) + try: + program_node, = program_obj.m_linktask.m_outputs + except AttributeError: + Params.fatal("%s does not appear to be a program" % (program_name,)) + + execvec = shlex.split(command_template % (program_node.abspath(env),)) - execvec = [program_node.abspath(env)] + argv[1:] former_cwd = os.getcwd() os.chdir(Params.g_cwd_launch) try: - return _run_argv(execvec) + retval = _run_argv(execvec) finally: os.chdir(former_cwd) + return retval + def run_shell(): if sys.platform == 'win32':