Compare commits

...

924 Commits

Author SHA1 Message Date
Tom Henderson 2c813805e7 Remove doc/build-waf.txt 2007-07-16 22:43:10 -07:00
Tom Henderson 0583ab3bc8 changes for 3.0.4 release 2007-07-16 21:41:19 -07:00
Gustavo J. A. M. Carneiro ae8f10ae47 WAF: derive the variable NS3_MODULES from the 'all_modules' list in src/wscript, instead of requiring every module to define a configure function to register themselves. This way module registration is done in one place only: src/wscript. Requires module naming conventions, though. 2007-07-15 13:04:47 +01:00
Gustavo J. A. M. Carneiro b6c0155487 Make Simulator::IsExpired parameter const, to reflect the fact that the EventId is not changed. EventId::IsExpired and EventId::IsRunning also made const. 2007-07-12 12:41:37 +01:00
George F. Riley 42d93b9872 Simplifications to the point to point devices and channel 2007-07-13 10:40:10 +02:00
Gustavo J. A. M. Carneiro d757f69479 WAF: explain in the docs how to change the compilation flags. 2007-07-10 13:45:20 +01:00
Gustavo J. A. M. Carneiro 5629eae3ae WAF: don't change CXXFLAGS if CXXFLAGS is set in the OS environment (so that user CXXFLAGS take precedence). 2007-07-10 13:42:23 +01:00
Gustavo J. A. M. Carneiro 496313f56b WAF: add debugging symbols to optimized builds 2007-07-10 13:37:17 +01:00
Tom Henderson 67fa3a8c82 WAF: --update build-waf.txt; add note about waf configure, add waf dist/distclean, remove ./ as part of system path to waf 2007-07-09 06:43:11 -07:00
Gustavo J. A. M. Carneiro 3ce169b4e2 WAF: ignore errors on shutil.rmtree in dist_hook, so that waf dist works even when no docs were previously generated. 2007-07-09 14:36:40 +01:00
Gustavo J. A. M. Carneiro 441a8868a0 Fix unit test assertion failure error message (was printing the value instead of the expression itself) 2007-07-09 14:31:52 +01:00
Gustavo J. A. M. Carneiro 65f894b7ac WAF: --run now runs the specified program from the directory where waf was invoked. 2007-07-08 12:24:22 +01:00
Gustavo J. A. M. Carneiro de608e90c1 WAF: option --run now filters out programs not in the subtree starting at the launch dir 2007-07-07 18:10:54 +01:00
Gustavo J. A. M. Carneiro 0b32b0109f WAF: fix simple typo in error message. 2007-07-05 14:48:21 +01:00
Gustavo J. A. M. Carneiro 0f246d7f69 WAF: when the program specified by --run is not found, print a list of all available program names in the error message. 2007-07-05 14:44:00 +01:00
Gustavo J. A. M. Carneiro d30f4d66de WAF: make the --run option work again 2007-07-05 14:38:39 +01:00
Unknown 8b7716b380 Add payload size to UDP 2007-07-01 00:35:59 -07:00
Unknown 96a92d230e more verbose commenting of the sample 2007-07-01 00:21:14 -07:00
Mathieu Lacage 7bed39940e merge with head 2007-07-02 19:47:03 +02:00
Mathieu Lacage 5625551898 append correct unit when printing Time objects 2007-07-02 19:44:18 +02:00
Gustavo J. A. M. Carneiro fd479088ec WAF scripts update 2007-07-02 18:23:52 +01:00
Mathieu Lacage bedbfd18d7 add dox doc for header and trailer PrintTo and DoGetName 2007-06-29 08:18:16 +02:00
Mathieu Lacage 2756732458 add more internal documentation 2007-06-28 13:59:51 +02:00
Mathieu Lacage 3bb28c049f test and fix backward printing 2007-06-28 13:43:27 +02:00
Mathieu Lacage ce57b5d156 more asserts, add failing tests, fix them 2007-06-28 13:01:40 +02:00
Mathieu Lacage 23f4e85f87 fix basic tests, add new test, add a bunch of asserts, add XXX comment 2007-06-28 12:29:21 +02:00
Mathieu Lacage b937ec5a87 add failing assert 2007-06-28 12:00:00 +02:00
Mathieu Lacage 103a2527ce use pretty printing in ascii output 2007-06-28 11:52:50 +02:00
Mathieu Lacage 18e53720d1 change arp pretty printing to new format 2007-06-28 11:52:16 +02:00
Mathieu Lacage 35f80fc5c3 modify sample packet printer to use ipv4 and udp headers 2007-06-28 11:48:37 +02:00
Mathieu Lacage 993dc85f8f change default pretty printing output format, add doc to metadata data structures 2007-06-28 11:07:38 +02:00
Mathieu Lacage 99bd5418bc merge with head 2007-06-27 20:51:07 +02:00
Gustavo J. A. M. Carneiro 7c1e148ffa WAF: add a warning to the --high-precision-as-double option help text saying they it works in configure. 2007-06-21 12:33:50 +01:00
Gustavo J. A. M. Carneiro ffa52a935a WAF: simplify --debug-level option to only have debug and optimized as possible values (debug becomes the former ultradebug); Add a warning to some options help text saying they only work in configure. 2007-06-21 12:26:46 +01:00
Gustavo J. A. M. Carneiro 4b4b121366 WAF: be careful not to set gcc-specific flags (like -Werror) when using a non-gcc compiler. 2007-06-21 11:59:55 +01:00
Mathieu Lacage 2964b90925 add testcase, fix bug 2007-06-21 11:07:04 +02:00
Mathieu Lacage 50f2fc5a16 fix small variable name typo 2007-06-21 11:01:15 +02:00
Mathieu Lacage d879c3c54a merge from head 2007-06-21 09:40:57 +02:00
Gustavo J. A. M. Carneiro 3012f74206 WAF: configure dynamic path for the cygwin platform. 2007-06-21 00:38:58 +01:00
Gustavo J. A. M. Carneiro 91aa5250de Add Ipv4Address operator <, to allow Ipv4Address to be used in std::set; Closes #39. 2007-06-19 16:59:44 +01:00
Mathieu Lacage 75d762c0b9 fix small typos 2007-06-18 19:31:27 +02:00
Gustavo J. A. M. Carneiro 67454b117b Add Ipv4Mask == and != operators, similarly to Ipv4Address. 2007-06-18 18:01:28 +01:00
Gustavo J. A. M. Carneiro 3b96881ba2 Bug 37: NS_TEST_ASSERT_EQUAL 2007-06-18 15:55:47 +01:00
Mathieu Lacage 87c5cb5706 add separator support to backward printing 2007-06-13 00:20:53 +02:00
Mathieu Lacage f4911e544b update packet benchmark 2007-06-13 00:10:40 +02:00
Mathieu Lacage 10d053a838 comment the sample code a little bit 2007-06-13 00:07:17 +02:00
Mathieu Lacage c4ab5ba8ff add separator support to PacketPrinter 2007-06-13 00:02:57 +02:00
Mathieu Lacage 75bc2e9b0b sample code for pretty printing 2007-06-12 23:40:14 +02:00
Mathieu Lacage c2fda9ce09 do not forget payload printer for default printer 2007-06-12 23:23:31 +02:00
Mathieu Lacage 8e2ee88b93 merge 2007-06-12 22:54:43 +02:00
Mathieu Lacage d27fe9ac8e merge 2007-06-12 22:54:10 +02:00
Mathieu Lacage 0d7b0e26ee history -> metadata 2007-06-12 22:52:56 +02:00
Gustavo J. A. M. Carneiro da531b4aef WAF: process --run and --shell command-line options sooner, before running the build, since we may need a shell before the build finishes, in case the program to debug is part of the build itself. 2007-06-12 19:04:38 +01:00
Gustavo J. A. M. Carneiro 4772e79fee Define env['NS3_MODULE_PATH'] in configure rather than build. 2007-06-12 18:52:58 +01:00
Gustavo J. A. M. Carneiro 72622c0755 Re-sync WAF build with the latest SConstruct changes. 2007-06-12 14:05:01 +01:00
Mathieu Lacage 55f2084e86 avoid duplicating the packet uid 2007-06-12 13:21:06 +02:00
Mathieu Lacage f34463d1cc add release notes 2007-06-12 11:37:56 +02:00
Mathieu Lacage 76b31adc2f fix bug 29 2007-06-12 11:04:00 +02:00
Mathieu Lacage 641ecb2736 fix bug 28 2007-06-12 10:53:38 +02:00
Mathieu Lacage 3dbf735aeb fix main dox entry point 2007-06-11 17:54:06 +02:00
Mathieu Lacage 33a493fe5d IIpv4 -> Ipv4 2007-06-11 17:50:16 +02:00
Mathieu Lacage 1ec3ab4a1f merge with HEAD 2007-06-11 17:47:49 +02:00
Gustavo J. A. M. Carneiro 005d9c9877 Add my institutional email address (gjc@inescporto.pt), in addition to the GMail one. 2007-06-08 18:58:34 +01:00
Mathieu Lacage 102dcfd4bc do not crash is the payload printer is null 2007-06-07 13:19:25 +02:00
Mathieu Lacage e89ad0a86b fix uleb128 reading bug 2007-06-07 13:16:15 +02:00
Mathieu Lacage b7ded4e595 PacketHistory -> PacketMetadata 2007-06-07 12:51:57 +02:00
Mathieu Lacage b61417101f rename packet-history.h to packet-metadata.h 2007-06-07 12:48:52 +02:00
Mathieu Lacage 6e2d898443 add an option to control the history implementation 2007-06-07 12:44:44 +02:00
Mathieu Lacage 1ba5c01281 more dox 2007-06-07 12:42:44 +02:00
Mathieu Lacage c6f42b1cff constify Callback::IsNull 2007-06-07 12:30:52 +02:00
Mathieu Lacage 2b3882fb1a make the code match the dox doc 2007-06-07 12:29:38 +02:00
Mathieu Lacage 12476595ad improve dox doc 2007-06-07 12:29:27 +02:00
Mathieu Lacage 8435bfc4fe add back optimization option 2007-06-07 12:25:40 +02:00
Mathieu Lacage 9cec524f88 rename History::Enable to Packet::EnableMetadata 2007-06-07 12:17:25 +02:00
Mathieu Lacage fb3786c137 remove dead code 2007-06-07 11:38:06 +02:00
Mathieu Lacage 40e654dd22 store chunkUid and packetUid as fixed-size fields 2007-06-07 11:21:21 +02:00
Mathieu Lacage d5087e2d90 unconditionally set m_data 2007-06-07 11:00:49 +02:00
Mathieu Lacage adf49bbc32 fix gcov link 2007-06-07 10:51:25 +02:00
Mathieu Lacage 8361cbab71 try alternative implementation of AddSmall 2007-06-07 10:38:48 +02:00
Mathieu Lacage 49abdbd009 fix Append and optimize GetUleb128Size 2007-06-07 09:38:51 +02:00
Mathieu Lacage 4b95d67bea optimize a bit AddHeader 2007-06-07 09:18:04 +02:00
Mathieu Lacage a6382422df remove atStart arg to AddBig 2007-06-07 08:13:19 +02:00
Mathieu Lacage e77c211955 remove ReadSmall and ReadExtra 2007-06-07 07:39:47 +02:00
Mathieu Lacage 8a3e4b7b14 ReadItems does not depend on ReadSmall & ReadExtra 2007-06-07 07:32:10 +02:00
Mathieu Lacage a0901958a8 make some methods inline 2007-06-06 14:40:48 +02:00
Mathieu Lacage 8e0ccbb45a Update -> UpdateHead + UpdateTail 2007-06-06 14:38:52 +02:00
Mathieu Lacage 1608934b89 simplify a bit the small item logic 2007-06-06 14:32:17 +02:00
Mathieu Lacage 02763bf7cb fix bug introduced in commit 767 2007-06-06 14:19:21 +02:00
Mathieu Lacage e5b63ce34d add counters 2007-06-06 14:14:22 +02:00
Mathieu Lacage 4ed6463d22 remove Update call from within AddSmall and AddBig 2007-06-06 14:11:22 +02:00
Mathieu Lacage f348fc4fbc remove useless CanAdd 2007-06-06 13:56:42 +02:00
Mathieu Lacage 07489e7e9c a few micro-optimizations 2007-06-06 13:51:15 +02:00
Mathieu Lacage eb6eea0f72 make all tests pass 2007-06-06 13:02:00 +02:00
Mathieu Lacage b0a30b32bb implement ReplaceTail 2007-06-06 12:39:33 +02:00
Mathieu Lacage 2caaf90037 simplify calls to AddBig and AddSmall 2007-06-06 11:30:17 +02:00
Mathieu Lacage 929ea4dab0 share some code, implement AddAtEnd 2007-06-06 11:01:59 +02:00
Mathieu Lacage f5ce4791d2 IUdp -> Udp 2007-06-06 10:54:58 +02:00
Mathieu Lacage 5698e745c9 fix a few bugs in ::RemoveAtEnd 2007-06-06 10:04:02 +02:00
Mathieu Lacage 8c03ce9e0c remove data from end of trailer, not start of header 2007-06-06 09:55:01 +02:00
Mathieu Lacage 113e6255ea simplify GetTotalSize 2007-06-06 09:45:23 +02:00
Mathieu Lacage cbac246ffb fix simple bugs in RemoveAtEnd 2007-06-06 09:43:54 +02:00
Mathieu Lacage e829515b02 fix fragment printing 2007-06-06 09:23:47 +02:00
Mathieu Lacage 3e511d1457 rewrite PacketHistory::RemoveAtstart 2007-06-06 09:13:21 +02:00
Mathieu Lacage aabed928b1 make sure that we set the low bit for typeUid when writing a 'big' item 2007-06-06 08:54:11 +02:00
Mathieu Lacage 6816e303ec implement PacketHistory::RemoveAtStart 2007-06-06 08:49:15 +02:00
Mathieu Lacage 1bbf7ce1a2 when doing a copy of a buffer, make sure to clear the prev and next fields 2007-06-05 21:48:26 +02:00
Mathieu Lacage 969ff1267e the mask to filter out the low bit is 0xfe, not 0xfd 2007-06-05 18:28:37 +02:00
Mathieu Lacage 3634046dc7 fix a bunch of buggy asserts 2007-06-05 17:35:22 +02:00
Mathieu Lacage c3ff0ad584 fix the list iteration logic 2007-06-05 16:40:05 +02:00
Mathieu Lacage ebfe75384c rename begin to head and end to tail 2007-06-05 16:36:53 +02:00
Mathieu Lacage bd1dcf3f97 fix field ordering. 2007-06-05 16:33:45 +02:00
Mathieu Lacage d5e147d400 deal with packet with zero headers correctly 2007-06-05 15:59:07 +02:00
Mathieu Lacage 35dbade0a9 implement PacketHistory::Print 2007-06-05 15:47:29 +02:00
Mathieu Lacage dc62fabc0b fix addition of a trailer or a header 2007-06-05 14:06:58 +02:00
Mathieu Lacage 47f2db1e23 a new implementation of the PacketHistory API 2007-06-05 13:44:43 +02:00
Mathieu Lacage 967b3f34e9 IIpv4 -> Ipv4 2007-06-04 18:25:43 +02:00
Mathieu Lacage 09ed1c9575 i-ipv4.h -> ipv4.h 2007-06-04 18:05:36 +02:00
Mathieu Lacage f71d6fd74f IUdp -> Udp 2007-06-04 18:03:26 +02:00
Mathieu Lacage b9c4fa85f1 i-udp.h -> udp.h 2007-06-04 18:01:09 +02:00
Mathieu Lacage c32fa46161 ISocketFactory -> SocketFactory 2007-06-04 17:57:01 +02:00
Mathieu Lacage d0bd4ea161 i-socket-factory.h -> socket-factory.h 2007-06-04 17:54:56 +02:00
Mathieu Lacage 7b6d5c4e97 IIpv4Private -> Ipv4Private 2007-06-04 17:42:37 +02:00
Mathieu Lacage 0459737b00 IIpv4Impl -> Ipv4Impl 2007-06-04 17:40:09 +02:00
Mathieu Lacage 372ecb8430 preprocessor update 2007-06-04 17:24:45 +02:00
Mathieu Lacage 9a852e442e IUdpImpl -> UdpImpl 2007-06-04 17:24:18 +02:00
Mathieu Lacage 92757ef5c3 Udp -> UdpL4Protocol 2007-06-04 17:22:52 +02:00
Mathieu Lacage 297692d88b udp.h -> udp-l4-protocol.h 2007-06-04 17:18:02 +02:00
Mathieu Lacage 4ead4618e6 i-arp-private.h -> arp-private.h 2007-06-04 17:14:59 +02:00
Mathieu Lacage 96f1c67bfe i-udp-impl.h -> udp-impl.h 2007-06-04 17:13:21 +02:00
Mathieu Lacage 9db1449b4b i-ipv4-private.h ipv4-private.h 2007-06-04 17:06:03 +02:00
Mathieu Lacage 9421bfcfee i-ipv4-impl.h -> ipv4-impl.h 2007-06-04 16:59:51 +02:00
Mathieu Lacage a5a1152e95 Arp -> ArpL3Protocol 2007-06-04 16:57:24 +02:00
Mathieu Lacage 3a97fce182 arp.h -> arp-l3-protocol.h 2007-06-04 16:54:36 +02:00
Mathieu Lacage e8ab5afb41 Ipv4 -> Ipv4L3Protocol 2007-06-04 16:51:59 +02:00
Mathieu Lacage 1d0658dc85 rename ipv4.h to ipv4-l3-protocol.h 2007-06-04 16:42:10 +02:00
Mathieu Lacage 01f37ccb65 rename MakeNewObject to Create 2007-06-04 16:32:37 +02:00
Mathieu Lacage 4d5a66d6e5 remove MakeInternetNode 2007-06-04 16:28:18 +02:00
Mathieu Lacage c4234041bc remove file 2007-06-04 16:24:05 +02:00
Mathieu Lacage 359a2f98a8 rename i-node to node 2007-06-04 16:21:05 +02:00
Mathieu Lacage 1225b1623e rename INode to Node 2007-06-04 16:17:01 +02:00
Mathieu Lacage 62aa29999b remove dead typedef 2007-06-04 09:33:38 +02:00
Mathieu Lacage a4f727f68d a bunch of optimizations 2007-06-03 20:09:56 +02:00
Mathieu Lacage a6c8a11881 fix the packet benchmark and enable it 2007-06-02 19:10:35 +02:00
Mathieu Lacage ce4bcba2e6 Added tag packet-history-working for changeset 0dc81e76166c 2007-06-02 18:36:56 +02:00
Mathieu Lacage a88ff1f2c4 more tests, fix 2007-06-02 18:32:31 +02:00
Mathieu Lacage a986e81353 more tests, initial fix. 2007-06-02 18:24:44 +02:00
Mathieu Lacage b9899de6df more tests 2007-06-02 18:13:19 +02:00
Mathieu Lacage bebb4eb281 fix build for g++ 4.1 2007-06-02 18:08:04 +02:00
Mathieu Lacage 03ca60cd50 merge with trunk 2007-06-02 17:59:14 +02:00
Mathieu Lacage 1c46ed54e5 merge with trunk 2007-06-02 17:58:39 +02:00
Mathieu Lacage 34c6957f95 more tests 2007-06-01 15:26:21 +02:00
Mathieu Lacage 8a62c228b2 ensure that packets are real buffers before concatenating them 2007-06-01 15:23:30 +02:00
Mathieu Lacage 4c92dfe914 add more asserts, make TransformIntoRealBuffer public for Packet class 2007-06-01 15:23:07 +02:00
Mathieu Lacage 5f2b952521 enable more tests 2007-06-01 14:50:04 +02:00
Mathieu Lacage 3485d9829c more tests 2007-06-01 14:35:18 +02:00
Mathieu Lacage 00d6bb5c8a add more tests 2007-06-01 13:06:35 +02:00
Mathieu Lacage 89fc9310db calculate the correct size of header and trailer to remove from buffer 2007-06-01 13:06:21 +02:00
Mathieu Lacage 26e52f0da4 more tests 2007-06-01 12:49:10 +02:00
Mathieu Lacage 99c235760e new test and fix to make it pass 2007-06-01 12:46:23 +02:00
Mathieu Lacage 0dfdcfbdc3 add test and fix buggy assert 2007-06-01 12:42:29 +02:00
Gustavo J. A. M. Carneiro 5f48c4e7f3 add waf.bat for convenience (waf itself still has to be manually copied from outside, though) 2007-06-18 10:53:48 +01:00
Tom Henderson 5e703c70f7 Added tag release ns-3.0.3 for changeset 38099dd26e94 2007-06-17 16:04:52 -07:00
Tom Henderson e9ae18f809 bump VERSION number 2007-06-17 16:04:12 -07:00
Tom Henderson 396c76892c release_steps.txt document 2007-06-17 14:17:22 -07:00
Mathieu Lacage c329d7dd4e improve Packet Header/Trailer API dox 2007-06-16 17:15:58 +02:00
Tom Henderson ca3871e4f6 Backed out changeset 767 for the release (not ready) 2007-06-15 13:30:40 -07:00
Tom Henderson d1c6c9a348 back out unfinished p2p changes 2007-06-15 13:19:57 -07:00
Gustavo J. A. M. Carneiro d5260811dc Add a Packet::AddAtEnd unit test. 2007-06-15 18:10:40 +01:00
Gustavo J. A. M. Carneiro ce155b4d35 WAF: remove debugging print accidentally left in. 2007-06-15 15:25:01 +01:00
Gustavo J. A. M. Carneiro 65aca43f3f WAF: make all ns3 modules register themselves in the environment; link the run-tests program with all ns3 modules, not with a hardcoded list. 2007-06-15 15:19:38 +01:00
Gustavo J. A. M. Carneiro 96418f577d re-sync cairo-wideint.c with upstream cairo's version (also fixes the recent compiler warning, but in a different way) 2007-06-14 13:09:56 +01:00
Gustavo J. A. M. Carneiro 2ee9064175 merge 2007-06-14 12:55:24 +01:00
George F. Riley 4042681e83 Simplification to p2p-net-device and p2p-channel (work in progress) 2007-06-14 10:41:47 +02:00
Tom Henderson cdf13df87d Add main-query-interface.cc sample file 2007-06-13 23:13:21 -07:00
Gustavo J. A. M. Carneiro 50037ae611 Fix compilier warning/error: src/simulator/cairo-wideint.c:789: warning: comparison between signed and unsigned integer expressions. 2007-06-13 18:40:38 +01:00
Gustavo J. A. M. Carneiro e38244e7c0 WAF: add -Wall and -Werror to CXXFLAGS, like in the SCons build. 2007-06-13 18:34:05 +01:00
Mathieu Lacage 4f0eae4a6d add a rationale for the way Trailers work 2007-06-13 16:37:04 +02:00
Mathieu Lacage 438e58cc1c add test and fix buggy assert 2007-06-01 12:42:29 +02:00
Mathieu Lacage 4bfd1c4a2a Packet API must call Trailer::DoSerialize on end of trailer, not start of trailer 2007-06-01 11:37:19 +02:00
Mathieu Lacage abfdb4befc test payload 2007-06-01 11:17:59 +02:00
Mathieu Lacage 5a1ffabd03 test fragments 2007-06-01 11:12:55 +02:00
Mathieu Lacage 66bf48b6e6 make the tests pass again 2007-06-01 11:03:56 +02:00
Mathieu Lacage bf7acebc30 fix buggy assert 2007-06-01 10:49:17 +02:00
Mathieu Lacage 975c1dc46f build the ItemList into the input list, not a temporary stack variable. 2007-06-01 10:35:05 +02:00
Mathieu Lacage 8cf2162121 remove PrintSimple and revert order of history data written in data buffer 2007-06-01 10:06:35 +02:00
Mathieu Lacage 9980528f1e make chunkUid zero and invalid uid to improve debugging 2007-06-01 09:55:47 +02:00
Tom Henderson 0e34f6cfb8 Touch file for test checkin 2007-05-31 08:20:09 -07:00
Mathieu Lacage 581b34b586 force use of the ItemList to test it 2007-05-31 14:52:15 +02:00
Mathieu Lacage 20581afe80 re-implement PacketHistory to use the PacketPrinter and work on ItemList::Print 2007-05-31 14:30:34 +02:00
Mathieu Lacage 3861a96d5a implement forgotten PacketPrinter::AddDefaultPrinter 2007-05-31 14:30:07 +02:00
Mathieu Lacage af44bde349 fix off-by-one in uid allocation 2007-05-31 14:00:03 +02:00
Mathieu Lacage 4736067ed2 avoid recursive initialization of uid static variable 2007-05-31 13:52:29 +02:00
Mathieu Lacage 2e686bcca7 use Callback::GetImpl rather than Callback::PeekImpl 2007-05-31 13:45:03 +02:00
Mathieu Lacage 8eef599aa6 add public Callback::GetImpl 2007-05-31 13:44:40 +02:00
Mathieu Lacage afb85320bf constify, allow ItemList access to private methods 2007-05-31 13:37:05 +02:00
Mathieu Lacage 4b8dabddae add support for a default PacketPrinter 2007-05-31 12:34:33 +02:00
Mathieu Lacage ab5c0a43bd rework the PacketPrinter code 2007-05-31 11:03:42 +02:00
Mathieu Lacage 65f215eee2 add a new overloaded Assign method 2007-05-31 11:03:26 +02:00
Mathieu Lacage e7abed2def try to design a packer printer class 2007-05-30 12:45:32 +02:00
Mathieu Lacage 66c3a25fe1 add Chunk::GetName and implement it 2007-05-30 10:03:15 +02:00
Mathieu Lacage d9f03cafbe implement ItemList::AddAtEnd 2007-05-30 09:48:53 +02:00
Mathieu Lacage 639231388c implement ItemList construction 2007-05-30 07:42:56 +02:00
Mathieu Lacage fe44d27cde prepare for forward iteration of history. 2007-05-29 16:53:53 +02:00
Mathieu Lacage b71248e0f3 keep track of the aggregation state 2007-05-29 16:24:40 +02:00
Mathieu Lacage 4db6e9a69a merge unfinished packet history code 2007-05-29 16:09:20 +02:00
Mathieu Lacage a6d6859aab sample code for component manager 2007-05-25 21:53:24 +02:00
Mathieu Lacage 55f8e04570 add more code to sample code 2007-05-25 21:47:59 +02:00
Mathieu Lacage a1f206804c sample code for Object base class 2007-05-25 21:43:23 +02:00
Mathieu Lacage 18c3f768a3 small typo 2007-05-25 21:28:38 +02:00
Mathieu Lacage 0e277a28d8 improve dox 2007-05-25 21:27:58 +02:00
Gustavo J. A. M. Carneiro 081e70c7f3 Add the waf files and scripts to the scons dist 2007-05-25 19:14:05 +01:00
Mathieu Lacage 44007809fd size of element is pointer, not value 2007-05-25 18:51:04 +02:00
Mathieu Lacage 827e1c879e avoid checking for the Object::iid value from within ComponentManager::Register 2007-05-25 18:39:02 +02:00
Mathieu Lacage 1a7e6629fb more tests 2007-05-25 18:22:22 +02:00
Mathieu Lacage 4164903d0e eliminate memory leak 2007-05-25 18:13:01 +02:00
Mathieu Lacage 5bedcf0a1c add dox 2007-05-25 18:00:50 +02:00
Mathieu Lacage f1db331e5d fix buggy assert 2007-05-25 17:42:53 +02:00
Mathieu Lacage 3df39a1f78 add DefaultValue support for ClassId 2007-05-25 15:28:24 +02:00
Mathieu Lacage 59459fc6ca a new ComponentManager API 2007-05-25 14:15:03 +02:00
Mathieu Lacage 83dcd91223 make Callback use a separate empty type 2007-05-25 14:13:23 +02:00
Mathieu Lacage ca530216ec add a m_disposed field and check it 2007-05-25 12:27:40 +02:00
Mathieu Lacage c2ac40ca00 use a 16 bit interface id 2007-05-25 12:23:51 +02:00
Mathieu Lacage 14e59ca91a remove buggy assert 2007-05-25 12:19:58 +02:00
Mathieu Lacage 643522774e port code from Interface to Object 2007-05-25 10:56:03 +02:00
Mathieu Lacage cb3ec490a5 make QueryInterface const 2007-05-25 10:52:58 +02:00
Mathieu Lacage 4358b2fd71 port ComponentManager to Object from Interface 2007-05-25 10:32:34 +02:00
Mathieu Lacage 6c6a0073bf remove Interface 2007-05-25 10:04:38 +02:00
Mathieu Lacage f86cf8b9c3 rename InterfaceObject to Object 2007-05-25 10:02:50 +02:00
Mathieu Lacage 0444eb1f80 remove Object base class 2007-05-25 09:44:57 +02:00
Mathieu Lacage 45d2ebfc69 merge 2007-05-25 09:44:18 +02:00
Gustavo J. A. M. Carneiro acbfbc29b3 WAF: add a dist_hook function to exclude the generated documentation from waf dist 2007-05-24 19:21:50 +01:00
Gustavo J. A. M. Carneiro 923f4aeb8f WAF: correct values of VERSION and APPNAME, for waf dist 2007-05-24 17:59:30 +01:00
Gustavo J. A. M. Carneiro 381103678d WAF: cleanup the main wscript file by moving the definition of the ns3header object type into src/wscript 2007-05-24 17:54:51 +01:00
Mathieu Lacage 80247a993d uniformize the DefaultValues used by the Event Schedulers 2007-05-24 16:15:41 +02:00
Mathieu Lacage 29026f00db merge 2007-05-24 16:12:20 +02:00
Mathieu Lacage 25c6350a88 fix bug 24 2007-05-24 16:08:03 +02:00
Gustavo J. A. M. Carneiro c0af811d13 WAF: reference-list* were removed 2007-05-24 14:53:43 +01:00
Mathieu Lacage 01d21b3ea2 add tests and fix leak 2007-05-24 15:37:00 +02:00
Mathieu Lacage df1cd3d5da remove ReferenceList: fix bug 27 2007-05-24 15:23:11 +02:00
Mathieu Lacage 1bab5a3625 add Callback::Nullify method 2007-05-24 14:58:24 +02:00
Mathieu Lacage 911daba417 fix bug 23 2007-05-24 14:53:10 +02:00
Mathieu Lacage 9b4e7f4cfc add DefaultValue support for TimeStepPrecision 2007-05-24 09:34:58 +02:00
Mathieu Lacage 8c4e057c91 add EnumDefaultValue::SetValue 2007-05-24 09:34:43 +02:00
Mathieu Lacage cd0c502986 more dox improvements 2007-05-24 09:22:48 +02:00
Mathieu Lacage 7436c51592 improve dox 2007-05-24 09:18:42 +02:00
Mathieu Lacage 95863b81a3 add reference to Emmanuelle in Authors/Copyright 2007-05-24 09:11:46 +02:00
Mathieu Lacage 49fbbec138 avoid cyclic dependency between Simulator and Time code 2007-05-24 09:08:24 +02:00
Mathieu Lacage cc2d1399ab fix small typos 2007-05-24 09:04:19 +02:00
Mathieu Lacage fcf02a427c namespace the precision values properly 2007-05-24 09:02:17 +02:00
Emmanuelle Laprise 73a66e5b1a Fixed the problems that were found by Mathieu Lacage in the first
implementation. Biggest change is to not allow any conversions to
double with the GetXxxSeconds and XxxSeconds functions. (see Bug 22
for more information)
2007-05-21 22:14:09 -05:00
Mathieu Lacage 8b48c39675 rename ::Add to ::AddInterface 2007-05-19 13:41:50 +02:00
Mathieu Lacage 055f6d06ae yet another optimization to cut even more on memory allocations 2007-05-19 13:25:45 +02:00
Emmanuelle Laprise 23ab5ba436 The header file ns3/cairo-wideint-private.h was added since the type int32_t was used. 2007-05-17 12:12:44 -05:00
Mathieu Lacage a655f02fcc merge ns-3.0.2 tag 2007-05-24 08:34:41 +02:00
Mathieu Lacage 92aa47e0bc Added tag release ns-3.0.2 for changeset 7ac5a4b0969b 2007-05-24 08:33:44 +02:00
Gustavo J. A. M. Carneiro 8cdcda24e1 WAF: remove the rpath options, and add --run and --shell as replacements; additionally, the new options "should" work on Mac OS X, as well as linux2 and win32. 2007-05-23 19:20:54 +01:00
Gustavo J. A. M. Carneiro a28dd7dbc3 WAF: cleanup code by putting lcov and doxygen handling into their own separate functions 2007-05-23 17:32:32 +01:00
Raj Bhattacharjea cd7fdcf026 Added comparison operators for DataRate 2007-05-21 13:22:37 -04:00
Gustavo J. A. M. Carneiro 81b081c67d WAF: sync with the last SConstruct change (smartvector.h and smartset.h removed) 2007-05-20 18:06:31 +01:00
Gustavo J. A. M. Carneiro fb07f84709 WAF: fix problem in --enable/disable-rpath options 2007-05-20 18:05:30 +01:00
Mathieu Lacage 0c0f992a5c merge 2007-05-20 14:38:53 +02:00
Mathieu Lacage 64663cf3bd remove unused code 2007-05-20 14:34:46 +02:00
Gustavo J. A. M. Carneiro e518ba5de5 Fix swapped parameters in LogNormalVariable::GetSingleValue and add a couple of LogNormalVariable unit tests. 2007-05-19 16:40:40 +01:00
Gustavo J. A. M. Carneiro 2dc08498c4 Correct the Ptr (T *ptr) documentation. 2007-05-19 14:37:06 +01:00
Tom Henderson f3135499c2 Verified build on x86_64 2007-05-18 14:08:51 -07:00
Tom Henderson 5e093d105a Remove codingstd.tex 2007-05-18 12:18:55 -07:00
Mathieu Lacage b09393e580 add VERSION to extra dist 2007-05-18 20:57:02 +02:00
Mathieu Lacage 43c9310f2e merge 2007-05-18 20:48:36 +02:00
Mathieu Lacage b862b62fb9 pull version number from VERSION file 2007-05-18 20:48:24 +02:00
Tom Henderson e8d95c4e7e Pick up codingstd.txt in dist; point interested waf users to build-waf.txt in the development branch 2007-05-18 11:13:57 -07:00
Tom Henderson 234aafe368 minor changes due to documentation review 2007-05-18 10:27:42 -07:00
Mathieu Lacage 418ceadc2b add doc/architecture.pdf to dist 2007-05-18 18:06:00 +02:00
Mathieu Lacage 12840fd46c update the documentation section 2007-05-18 18:03:48 +02:00
Raj Bhattacharjea 8dd140d50d Make scons dist work on osx 2007-05-18 11:41:43 -04:00
Mathieu Lacage 81da9b6187 merge 2007-05-18 17:28:15 +02:00
Mathieu Lacage fdfcb95711 change version number to match ns convention 2007-05-18 17:26:28 +02:00
Gustavo J. A. M. Carneiro 8d9a65d226 WAF: enable -rpath by default only on linux2, with configure options to override this default choice 2007-05-18 16:09:13 +01:00
Gustavo J. A. M. Carneiro 777438f7fc WAF: the correct form of the rpath option should be -rpath, not --rpath; fixed. 2007-05-18 11:27:20 +01:00
Gustavo J. A. M. Carneiro d386be9d5d WAF: import the WAF subprocess replacement module 'pproc', to make it work on Python 2.3. 2007-05-17 18:22:10 +01:00
Gustavo J. A. M. Carneiro 78f81de607 Make WAF scripts modify PATH in environment to allow child processes to find the ns-3 DLLs, instead of using --rpath, which doesn't work on win32. This way at least waf check is able to run the unit tests now. 2007-05-17 17:34:19 +01:00
Gustavo J. A. M. Carneiro b3b7a98b8e In WAF win32 builds, add -Wl,--enable-runtime-pseudo-reloc to LINKFLAGS to solve dll linking problems. 2007-05-17 17:02:03 +01:00
Mathieu Lacage b1bc31ae0e optimization suggested by gustavo 2007-05-17 17:21:49 +02:00
Gustavo J. A. M. Carneiro 4c68aff164 Rename the SocketErrno enumeration values, from ESOMETHING to ERROR_SOMETHING, to avoid conflict with errno #define's; fixes compilation in mingw32. 2007-05-17 15:50:20 +01:00
Mathieu Lacage b3d1e90132 add benchmark by gustavo 2007-05-17 16:45:03 +02:00
Gustavo J. A. M. Carneiro 6e7e5822fb Fix some case sensitivity issues on win32-specific code. 2007-05-17 15:15:56 +01:00
Mathieu Lacage 237de8786b merge 2007-05-17 16:00:02 +02:00
Mathieu Lacage 6f9b937819 add gcc 4.2 to list of supported compilers 2007-05-17 15:59:23 +02:00
Gustavo J. A. M. Carneiro 96535936a5 Make WAF check for the abstract tool 'compiler_cxx', instead of manually checking for multiple compilers. 2007-05-17 14:22:27 +01:00
Mathieu Lacage f2c02fe3bb a replacement for the Interface base class 2007-05-17 14:39:54 +02:00
Mathieu Lacage 38ab245727 add reference to architecture document 2007-05-17 14:31:08 +02:00
Mathieu Lacage 447de493d3 beautify the dox output 2007-05-17 14:07:22 +02:00
Mathieu Lacage f03a672ac0 cleanup old dox and reorg header 2007-05-17 12:28:38 +02:00
Mathieu Lacage 6a4d33e3e6 improve IIpv4 dox 2007-05-17 12:23:39 +02:00
Mathieu Lacage aa0d967512 improve dist support 2007-05-17 11:46:33 +02:00
Mathieu Lacage fd0a70f87e add gustavo to AUTHORS 2007-05-17 11:35:49 +02:00
Mathieu Lacage 12ed9958e5 write README, contributing.txt, reorganize the other documentation files 2007-05-17 11:32:22 +02:00
Mathieu Lacage 58f1af736e fix scons dist and scons all for gcc 4.1 2007-05-17 07:51:22 +02:00
Raj Bhattacharjea 256582455b Some dox additions/fixes 2007-05-16 17:01:39 -04:00
Raj Bhattacharjea b852e0492e Internet-node module dox 2007-05-16 16:39:32 -04:00
Raj Bhattacharjea 37aa2a4bd2 Fixed a gcc3.4.6 error for optimized builds 2007-05-16 13:37:39 -04:00
Mathieu Lacage 6736b56964 fix dox warnings 2007-05-15 17:12:36 +02:00
Mathieu Lacage 41b12f96a5 remove references to Chunk and replace them with references to Header and Trailer 2007-05-15 16:42:53 +02:00
Mathieu Lacage 12fa2d9178 move doxygen doc into Header and Trailer classes. 2007-05-15 16:39:55 +02:00
Raj Bhattacharjea 7c4b2d67f6 Queue dox 2007-05-14 14:56:39 -04:00
Raj Bhattacharjea 487867d3aa MacAddress dox 2007-05-14 14:34:48 -04:00
Raj Bhattacharjea 29ba1c1c64 droptail and ipv4address dox 2007-05-14 14:07:26 -04:00
Raj Bhattacharjea 6c93b818af datarate, packet, defaultvalue, object dox 2007-05-14 10:38:08 -04:00
Raj Bhattacharjea 9d2216d84f fixed compiler error for gcc 3.4.6 2007-05-14 11:05:37 -04:00
Mathieu Lacage 093b8557ce fix build 2007-05-14 17:00:49 +02:00
Gustavo J. A. M. Carneiro cf9674a713 Update WAF scripts to changes in source tree layout 2007-05-14 13:46:53 +01:00
Mathieu Lacage ddeb64e4dd remove old crap 2007-05-14 13:04:59 +02:00
Mathieu Lacage 109139b07f make OnOffApplication not depend on IUdp 2007-05-14 12:59:44 +02:00
Mathieu Lacage ec9215fbc1 remove useless comment 2007-05-14 12:37:55 +02:00
Mathieu Lacage 222f309be5 more dox doc 2007-05-14 12:37:31 +02:00
Mathieu Lacage 0ae24ebd1b add some dox doc 2007-05-14 12:34:44 +02:00
Mathieu Lacage 94c5cf7457 implement and use the OnOffApplication default values 2007-05-14 12:33:17 +02:00
Mathieu Lacage 1a70acc7c5 add DefaultValue support to DataRate 2007-05-14 12:32:59 +02:00
Mathieu Lacage 866c4cd4ec add dox doc and DefaultValue support to OnOffApplication 2007-05-14 11:12:29 +02:00
Mathieu Lacage bae023c075 add a few features to IntegerDefaultValue 2007-05-14 11:11:30 +02:00
Mathieu Lacage a6d24b73bd simplify the implementation 2007-05-14 10:25:50 +02:00
Mathieu Lacage 791a45c3da remove dead keyword 2007-05-14 10:16:12 +02:00
Mathieu Lacage b3375209c0 remove dead code 2007-05-14 10:15:03 +02:00
Mathieu Lacage 3c3bea853e remove unused method 2007-05-14 10:08:01 +02:00
Mathieu Lacage ee02cd1a23 rename Node to INode 2007-05-14 10:06:12 +02:00
Mathieu Lacage 4ac0069541 add back internet-node.h header for MakeInternetNode function 2007-05-14 09:26:51 +02:00
Mathieu Lacage 0d9f136298 rename internet-node.h to i-node-impl.h 2007-05-14 09:26:32 +02:00
Mathieu Lacage 1b0dbb2b34 rename node.h to i-node.h 2007-05-14 09:09:43 +02:00
Gustavo J. A. M. Carneiro 01f945c459 Fix a small waf script bug, in the rpath code, that only appears when compiling for the first time. 2007-05-13 17:37:30 +01:00
Gustavo J. A. M. Carneiro 58651f9ff6 Update WAF SVN checkout instructions; now the URL points to a special WAF SVN tag that represents code tested to work with NS-3. 2007-05-13 13:58:34 +01:00
Gustavo J. A. M. Carneiro 7aacb7d136 merge 2007-05-13 12:52:38 +01:00
Gustavo J. A. M. Carneiro ca2416f431 WAF: simplify wscripts using the new chained uselib_local dependencies feature of WAF SVN; now build all samples and examples; add --disable-rpath configure option; add WAF build instructions. 2007-05-13 12:46:18 +01:00
Mathieu Lacage 19696ec37f add license header 2007-05-13 12:00:56 +02:00
Mathieu Lacage ec20424afb remove useless comment 2007-05-13 11:57:40 +02:00
Mathieu Lacage a9ffc5d23b complete dox doc 2007-05-13 11:57:27 +02:00
Mathieu Lacage 36b2223600 add dox documentation 2007-05-13 11:51:01 +02:00
Mathieu Lacage 52d60ea049 add dox documentation for Node 2007-05-13 11:46:11 +02:00
Mathieu Lacage 88c5dfecb0 make the Node API more consistent 2007-05-13 11:30:15 +02:00
Mathieu Lacage 1f454dd36e merge with trunk 2007-05-13 11:24:28 +02:00
Mathieu Lacage f1612bbc2c fix dox warnings 2007-05-13 10:57:43 +02:00
Mathieu Lacage a8bc213609 remove doxygen warnings 2007-05-13 10:46:44 +02:00
Mathieu Lacage d83bde7b0f improve doxygen output 2007-05-13 10:46:25 +02:00
Mathieu Lacage 293fb90057 improve doxygen output 2007-05-13 10:42:42 +02:00
Mathieu Lacage 05b444ae8a fix the doxygen comments and simplify the implementation 2007-05-13 10:24:35 +02:00
Mathieu Lacage b1574fba1a remove Application::Copy 2007-05-13 10:02:10 +02:00
Mathieu Lacage 87112f46f7 call Node::AddDevice from NetDevice::NetDevice 2007-05-13 09:58:53 +02:00
Mathieu Lacage 26c628e81a remove ApplicationList. Move functionality to Node class 2007-05-13 09:46:38 +02:00
Mathieu Lacage a37a156977 make Queue::CreateDefault use the ComponentManager. 2007-05-13 09:35:03 +02:00
Tom Henderson bca528b89a Remove unused code 2007-05-12 15:36:41 -07:00
Tom Henderson dc01b2136e Separate address assignment from routing in PointToPoint topology code 2007-05-12 15:31:40 -07:00
Tom Henderson 5c5ad7b16a Removing superseded code for p2p 2007-05-11 22:28:12 -07:00
Mathieu Lacage 3834d248de add a small comment 2007-05-11 22:33:51 +02:00
Mathieu Lacage b3aee2deb2 NetDevice and Channel now derive from Interface rather than Object 2007-05-11 19:26:01 +02:00
Mathieu Lacage 5cb92847c4 make Queue derive from Interface 2007-05-11 19:15:28 +02:00
Mathieu Lacage 666e00b097 rename Iid to InterfaceId 2007-05-11 18:57:45 +02:00
Mathieu Lacage e22e6188cf rename NsUnknown to Interface and NsUnknownManager to ComponentManager 2007-05-11 18:52:05 +02:00
Mathieu Lacage 6495c220a9 rename ns-unknown.h/cc ns-unknown-manager.h/cc 2007-05-11 18:42:39 +02:00
Raj Bhattacharjea e47155fe77 Added/fixed some doxygen 2007-05-11 10:37:01 -04:00
Mathieu Lacage 95280cac61 rename Erase to Remove as suggested by Tom 2007-05-11 10:11:06 +02:00
Mathieu Lacage 9be459e22f remove un-implemented method 2007-05-11 10:10:46 +02:00
Mathieu Lacage 6c2e4c823c add disabled test 2007-05-11 09:55:59 +02:00
Mathieu Lacage 2d8ed8d400 add small comment 2007-05-11 09:55:51 +02:00
Mathieu Lacage 24d19e29c0 rename Ptr::Get and Ptr::Peek to GetPointer and PeekPointer 2007-05-11 09:46:01 +02:00
Mathieu Lacage bc15f7157e remove useless assignments 2007-05-11 09:11:49 +02:00
Mathieu Lacage 720fae1bbe rework the refcounting framework to use the MakeNewObject function 2007-05-11 08:59:49 +02:00
Mathieu Lacage d82a6d11f9 add MakeNewObject template with more arguments 2007-05-11 08:59:11 +02:00
Mathieu Lacage 0e1388a2fd add MakeNewObject template function and fix operator == (T1,T2) 2007-05-11 08:35:41 +02:00
Mathieu Lacage 4bd2abebd2 use Ptr<> everywhere Object or NsUnknown are used 2007-05-10 20:19:26 +02:00
Mathieu Lacage 349f970d82 remove leaks and rework the Ptr class to work with a new refcount mechanism 2007-05-10 18:33:52 +02:00
Mathieu Lacage 01a20c0a82 add some refcount debugging 2007-05-10 09:57:46 +02:00
Mathieu Lacage db94cb6941 use the NS_DEBUG env var rather than NS3_DEBUG, as explained by the documentation. 2007-05-10 09:57:32 +02:00
Mathieu Lacage 2d66e7e804 make sure that NodeList::GetNode is correctly implemented 2007-05-10 08:34:32 +02:00
Mathieu Lacage 60734cd2db implement properly Application::DoDispose and rename Application::PeekNOde to Application::GetNode 2007-05-10 08:19:53 +02:00
Mathieu Lacage f5451f5bce rename NodeList::PeekNode to NodeList::GetNode 2007-05-10 08:19:19 +02:00
Mathieu Lacage e322d7f1df implement properly NetDevice::DoDispose and rename NetDevice::PeekNode to NetDevice::GetNode 2007-05-10 08:18:41 +02:00
Mathieu Lacage 96f4b45eab remove some dead code 2007-05-10 08:03:07 +02:00
Mathieu Lacage 11d883f2a6 remove useless forward declaration 2007-05-10 07:58:31 +02:00
Mathieu Lacage 66bc2db9d1 convert Node * to Ptr<Node> 2007-05-10 07:58:18 +02:00
Mathieu Lacage 96e58ed708 convert UdpSocket and Udp to Ptr<Node> 2007-05-10 07:51:59 +02:00
Mathieu Lacage ad8424e6d1 convert Node * to Ptr<Node> 2007-05-10 07:44:18 +02:00
Mathieu Lacage 817876d6fe convert Node * to Ptr<Node> 2007-05-10 07:43:52 +02:00
Mathieu Lacage 4d1c0647c8 remove useless forward declaration 2007-05-10 07:42:31 +02:00
Mathieu Lacage 5bd6229ac1 convert more code to use Ptr<Node> instead of Node * 2007-05-10 07:35:53 +02:00
Mathieu Lacage b67d398976 convert Arp code to use Ptr<Node> instead of Node * 2007-05-10 07:33:26 +02:00
Mathieu Lacage c12d5a1142 revert Ipv4Interface * -> Ptr<Ipv4Interface> 2007-05-10 07:30:37 +02:00
Mathieu Lacage 90a0cb3ad2 remove ptr from ArrayTraceResolver 2007-05-10 07:25:47 +02:00
Mathieu Lacage 2eb20b5743 merge 2007-05-10 07:19:38 +02:00
Unknown a70e279787 some Ipv4Interface* -> Ptr<Ipv4Interface>, and unhack arraytraceresolver, still segfaults 2007-05-09 23:23:05 -04:00
Mathieu Lacage a82cf78743 remove ptr::Remove, make ptr::Peek share the same signature as ptr::Get 2007-05-09 19:48:33 +02:00
Mathieu Lacage 80854a2c39 remove ptr::Remove, make ptr::Peek share the same signature as ptr::Get 2007-05-09 19:48:33 +02:00
Raj Bhattacharjea bd73c92bb5 Hacked arraytraceresolver to compile, but segfaults upon running simple-p2p 2007-05-09 16:56:33 -04:00
Raj Bhattacharjea de3b9c78f3 Removed manual ref/unref calls for Ptr<Node> 2007-05-09 14:50:14 -04:00
Raj Bhattacharjea ecfcfa977d Node* -> Ptr<Node> 2007-05-09 13:26:21 -04:00
Raj Bhattacharjea 4e32c8f56e Ptr changed to use Object's refcounts 2007-05-08 11:44:04 -04:00
Mathieu Lacage 5461e0a056 fix doxygen doc error 2007-05-09 17:07:50 +02:00
Gustavo J. A. M. Carneiro b2a87732c9 Add support for building with WAF 2007-05-07 12:01:51 +01:00
Tom Henderson ea55c60fe3 Enable both ascii and pcap tracing 2007-05-04 12:17:14 -07:00
Tom Henderson a6f05a05e0 Cosmetic: change strings in the bind commands for queue. Move Bind() before CommandLine::Parse() in example script 2007-05-04 11:50:02 -07:00
Mathieu Lacage 8819fdde7a make the code work on g++ 3.4.4 2007-05-07 23:05:17 +02:00
Mathieu Lacage 1808ad3c6d add extra test for object creation with multiple interfaces 2007-05-07 15:55:37 +02:00
Mathieu Lacage 440479be65 add more tests 2007-05-07 13:45:30 +02:00
Mathieu Lacage d35f6e80df use Callback::Assign 2007-05-07 13:45:15 +02:00
Mathieu Lacage 0bd8f12c64 use Callback::Assign 2007-05-07 13:44:33 +02:00
Mathieu Lacage 9e269500d2 add Callback::Assign 2007-05-07 13:44:22 +02:00
Mathieu Lacage 658cc9cd23 rework and document API 2007-05-07 13:21:29 +02:00
Mathieu Lacage aa4cf039bf a first draft of a component manager 2007-05-06 18:59:36 +02:00
Mathieu Lacage 4b68e3f7fe define class Iid to replace the uint32_t as suggested by Gustavo 2007-05-06 11:20:12 +02:00
Mathieu Lacage 6e437f5103 move code around 2007-05-04 15:04:07 +02:00
Mathieu Lacage ccd6f5b640 merge with HEAD 2007-05-04 14:03:12 +02:00
Raj Bhattacharjea c7db73ec6b Added static RNGs, like ExponentialVariable::GetSingleValue(mean) 2007-05-03 14:19:33 -04:00
Mathieu Lacage 4f05b2b2fc remove Node::GetIpv4 2007-05-03 15:24:34 +02:00
Mathieu Lacage b4810cc153 remove Node::GetArp 2007-05-03 14:39:37 +02:00
Mathieu Lacage 2f1189d766 remove Node::GetUdp 2007-05-03 14:23:41 +02:00
Mathieu Lacage b1eccbe7bf define and implement IUdp 2007-05-03 14:20:04 +02:00
Mathieu Lacage c2bd604574 remove spurious call to Dispose 2007-05-03 13:49:24 +02:00
Mathieu Lacage b15d1043d1 finish Dispose -> DoDispose rework 2007-05-03 13:24:43 +02:00
Mathieu Lacage e89d1692e5 make ApplicationList an NsUnknown object. 2007-05-03 13:17:29 +02:00
Mathieu Lacage b0399a9f9c fix valgrind warning: UdpSocket must manage carefully its Ipv4EndPoint to avoid double deleting it. 2007-05-03 13:11:50 +02:00
Mathieu Lacage 69ffe8defb make Ipv4L4Demux an NsUnknown object. 2007-05-03 12:46:50 +02:00
Mathieu Lacage 0e11e9f7f4 make L3Demux an NsUnknown object. 2007-05-03 12:33:08 +02:00
Mathieu Lacage 20d0136449 make Node derive from NsUnknown rather than Object 2007-05-03 11:08:13 +02:00
Mathieu Lacage 3e3d180edb disable the default constructor to avoid bugs 2007-05-03 11:06:51 +02:00
Mathieu Lacage 5b4433d50b add NsUnknown::Dispose 2007-05-03 11:01:26 +02:00
Mathieu Lacage 0db7be7cb8 rename the class itself 2007-05-03 10:58:08 +02:00
Mathieu Lacage 37434dca9c rename files 2007-05-03 10:49:28 +02:00
Mathieu Lacage 3ec8e09b8a airplane COM code 2007-05-03 10:34:35 +02:00
Mathieu Lacage db843fd786 remove more dead code 2007-05-03 00:37:48 +02:00
Mathieu Lacage 97f57a698b remove dead code 2007-05-03 00:35:39 +02:00
Mathieu Lacage 62a6143de1 remove dead code 2007-05-03 00:33:03 +02:00
Mathieu Lacage 5c9a4d2328 fix last leaks with new refcounted mechanism 2007-05-03 00:31:04 +02:00
Mathieu Lacage 66780ca8aa constify refcounted object base class 2007-05-03 00:23:23 +02:00
Mathieu Lacage 4a90819ba6 port sample code to refcounting model 2007-05-03 00:12:39 +02:00
Mathieu Lacage 08e8dbec66 remove dead method declaration and dead use 2007-05-02 23:45:26 +02:00
Mathieu Lacage 77a1488dd2 implement properly the refcounting rules for the capability getters 2007-05-02 23:42:22 +02:00
Mathieu Lacage e5d10e4bf7 make capabilities and sockets refcounted 2007-05-02 23:18:51 +02:00
Mathieu Lacage 5528c400d0 implement Dispose properly throughout the network stack 2007-05-02 23:08:41 +02:00
Mathieu Lacage 43154a6a64 use Dispose more extensively 2007-05-02 22:32:25 +02:00
Raj Bhattacharjea 34160210b4 Added default value sample 2007-05-02 15:23:35 -04:00
Raj Bhattacharjea b31f827d9b Merged in default code 2007-05-02 13:39:39 -04:00
Mathieu Lacage 3dbf9f25e1 rework the socket/udp layer to remove the Ipv4EndPointDemux template 2007-05-02 19:14:34 +02:00
Raj Bhattacharjea a158a93198 Randomvariable Lognormal added 2007-05-02 09:37:15 -04:00
Mathieu Lacage 2d41f0a3c1 fix segfault 2007-05-02 15:14:27 +02:00
Mathieu Lacage 9021652bd3 use ref/unref for Node in more cases 2007-05-02 15:07:33 +02:00
Mathieu Lacage 48899c0ba7 remove nil macro 2007-05-02 14:52:34 +02:00
Mathieu Lacage e24a6a189a remove dead files 2007-05-02 14:46:14 +02:00
Mathieu Lacage b20e550e89 remove nil macro 2007-05-02 14:43:18 +02:00
Mathieu Lacage ad230ae351 remove nil macro 2007-05-02 14:41:34 +02:00
Mathieu Lacage 0ee24c204f remove nil macro 2007-05-02 14:41:18 +02:00
Mathieu Lacage 43adf5863d apply ref/unref rules consistently for Node 2007-05-02 14:40:40 +02:00
Mathieu Lacage c5193f1e74 remove useless methode declaration 2007-05-02 14:28:07 +02:00
Mathieu Lacage 1893fea2ea rename NodeList::GetNode to NodeList::PeekNode to avoid memory leaks. Call Dispose from NodeListPriv::~NodeListPriv 2007-05-02 13:59:29 +02:00
Mathieu Lacage acf2d25cd5 rework the Node and NodeList classes to manage reference counts correctly 2007-05-02 13:44:41 +02:00
Mathieu Lacage 3cc6ff972b a singleton template class to simplify the implementation of a few classes 2007-05-02 13:43:41 +02:00
Mathieu Lacage c82b51d8da remove Node::Copy, Node::Create and Node::*Prototype* methods. 2007-05-02 12:34:53 +02:00
Mathieu Lacage 3b476dbd6c do not leak the NetDevice from P2PTopology 2007-05-02 12:12:55 +02:00
Mathieu Lacage a6e2a3fc30 do not leak the channel from simple-p2p 2007-05-02 11:43:22 +02:00
Mathieu Lacage 767fceb6f0 do not use Simulator::StopAt to avoid too many memory leaks 2007-05-02 11:38:21 +02:00
Mathieu Lacage 54e9226bdd make Application::Stop work 2007-05-02 11:37:52 +02:00
Mathieu Lacage 0c235e8edd improve debugger output for time variables when we do not need the 128 bit statistics 2007-05-02 11:22:27 +02:00
Mathieu Lacage 9bb706c627 destroy prototype stack upon Simulator::Destroy 2007-05-02 10:41:34 +02:00
Mathieu Lacage 6d4e502109 destroy the Node vector upon Simulator::Destroy rather than wait until the global static destructor of Node::g_nodes is invoked. This fixes a bad assert caught with valgrind. 2007-05-02 10:33:39 +02:00
Mathieu Lacage 1eeab81136 manage NetDevice objects with refcounts 2007-05-02 10:25:06 +02:00
Mathieu Lacage 5f7f31e7c9 temporarily invoke node's Dispose from user script 2007-05-02 10:24:59 +02:00
Mathieu Lacage b7ad24cea9 make sure that Simulator::Cancel deals correctly with events which were already scheduled 2007-05-02 10:20:44 +02:00
Mathieu Lacage 6e03b80cd0 call dispose from within the destructor 2007-05-02 09:18:18 +02:00
Mathieu Lacage d4814abf5f just a small typo 2007-05-02 09:18:02 +02:00
Mathieu Lacage cdee56670e derive from Object for proper refcounting 2007-05-02 09:17:42 +02:00
Mathieu Lacage 63a732f71e do not try to dispose the parent's ressources from InternetNode::Dispose 2007-05-02 09:17:17 +02:00
Mathieu Lacage 8c580647fd dispose properly from Node::Dispose 2007-05-02 09:16:58 +02:00
Mathieu Lacage fb6b984be4 add Object::Dispose 2007-05-02 09:16:32 +02:00
Mathieu Lacage 9eaf9191d8 merge in raj's dispose early work 2007-05-02 09:10:19 +02:00
Tom Henderson d4ddfc18f5 Provide correct exit value based on RunTests() success 2007-05-01 17:55:04 -07:00
Mathieu Lacage 4206fd3bce make sure that the code matches the documentation 2007-05-01 11:58:19 +02:00
Mathieu Lacage e8633acdca merge Packet API changes needed for Packet pretty printing. 2007-05-01 11:54:21 +02:00
Mathieu Lacage 47c1f224dc re-enable ascii trace output by default 2007-05-01 11:38:30 +02:00
Mathieu Lacage a49c5e804c merge with pcap branch 2007-05-01 11:35:27 +02:00
Mathieu Lacage 399ba068e1 remove DatagramSocket, use Socket base class for UdpSocket subclass. 2007-04-30 16:23:10 +02:00
Mathieu Lacage f3febd91ac remove unused headers 2007-04-30 10:37:57 +02:00
Mathieu Lacage 4873ff5f39 add NetDevice::SetReceiveCallback and use it 2007-04-30 10:37:22 +02:00
Mathieu Lacage 52646de997 use Node::AddDevice method 2007-04-30 10:24:43 +02:00
Mathieu Lacage f311b5f77b fix build 2007-04-30 10:24:30 +02:00
Mathieu Lacage 4219858cc2 remove external NetDeviceList and use the Node's integrated list 2007-04-30 10:21:49 +02:00
Mathieu Lacage 50e9149f90 add NetDevice list into Node base class 2007-04-30 10:16:04 +02:00
Mathieu Lacage bb58b03aef use NetDevice::NeedsArp where needed 2007-04-30 10:07:53 +02:00
Mathieu Lacage cd2fabe2f1 add NetDevice::NeedsArp method 2007-04-30 10:05:46 +02:00
Mathieu Lacage e63689a66f remove ipv4 interface from public API 2007-04-30 10:00:34 +02:00
Mathieu Lacage 6bc3146a79 handle const methods on const objects 2007-04-30 09:48:35 +02:00
Raj Bhattacharjea 327c365a41 Incorporated defaults and command-line arguments 2007-04-26 11:36:05 -04:00
Mathieu Lacage 75c78de2b3 a new testcase with the corresponding bug fix. 2007-04-19 22:29:09 +02:00
Mathieu Lacage 7f228cc6f4 remove debugging output from tests 2007-04-19 11:00:18 +02:00
Mathieu Lacage 48dee43f04 make sure that TagRegistry member variables are always initialized when needed. 2007-04-19 10:41:29 +02:00
Mathieu Lacage c0f7585f95 implement constructor/destructor handling for tags 2007-04-19 10:28:51 +02:00
Mathieu Lacage 363c64c04f fix optimized build warning 2007-04-19 10:28:10 +02:00
Unknown 207976b5fe merge with trunk 2007-04-18 19:17:13 +02:00
Unknown 50728fecb3 fix coding style 2007-04-18 19:16:03 +02:00
Unknown 859ea21294 more tests 2007-04-18 19:14:57 +02:00
Unknown f3a623dbbc fix failing test 2007-04-18 19:10:16 +02:00
Unknown dd8efc774c add failing test 2007-04-18 19:08:40 +02:00
Gustavo J. A. M. Carneiro a5d4a39e6d Fix Ptr<T>::m_count memory leak in some places. 2007-04-13 15:52:27 +01:00
Mathieu Lacage f7017e22a0 plug memory leak reported by Gustavo Carneiro. 2007-04-18 07:44:43 +02:00
Tom Henderson 504a77f44d Fix bug 14 2007-04-17 21:29:30 -07:00
Raj Bhattacharjea b1135d3e02 Removed the unnecessary Seed classes 2007-04-03 10:24:18 -04:00
Mathieu Lacage 35ae37acb5 Added tag release ns-3.0.1 for changeset 56928998e05c 2007-04-01 15:53:58 +02:00
Tom Henderson 7beaa02443 Final pre-release files 2007-03-30 15:39:02 -07:00
Raj Bhattacharjea e3b2ac5313 Fixed NormalVariable::INFINITE_VALUE 2007-03-30 10:42:23 -04:00
Mathieu Lacage 642ffe507f fix dox warning 2007-03-30 14:01:41 +02:00
Mathieu Lacage cf2e2f54c7 merge 2007-03-30 13:02:11 +02:00
Mathieu Lacage b37e67aec2 remove last warnings 2007-03-30 13:00:47 +02:00
Mathieu Lacage 5979e2483e fix more dox warnings 2007-03-30 12:37:02 +02:00
Mathieu Lacage 173dbba314 fix dox warnings 2007-03-30 11:08:47 +02:00
Craig Dowell 403f2419d6 fix queue leak and add p2p net device dox 2007-03-29 15:53:20 -07:00
Mathieu Lacage b83e6d9dfc remove SystemFile from doxygen index 2007-03-30 00:12:34 +02:00
Mathieu Lacage 6aba69af41 remove dead code 2007-03-30 00:11:51 +02:00
Mathieu Lacage 967740726a remove dependency on SystemFile 2007-03-30 00:10:59 +02:00
Mathieu Lacage aeed4279d7 add context information to tx and rx trace callbacks 2007-03-29 23:41:16 +02:00
Mathieu Lacage 3af7a78855 put together a PcapTrace and test it 2007-03-29 23:24:10 +02:00
Mathieu Lacage fbb179e7a6 add wifi pcap output 2007-03-29 22:49:28 +02:00
Mathieu Lacage 90107197c7 add ip output 2007-03-29 22:47:57 +02:00
Mathieu Lacage 9bc94d7f80 remove useless code 2007-03-29 22:39:26 +02:00
Mathieu Lacage 04a6e02b58 remove dead code 2007-03-29 22:39:11 +02:00
Mathieu Lacage 80edf00e0d start some doxygen template 2007-03-29 18:07:37 +02:00
Mathieu Lacage 0932fee6b2 more doc 2007-03-29 18:04:56 +02:00
Mathieu Lacage b6c62d5650 add empty template for doxygen doc 2007-03-29 18:04:06 +02:00
Mathieu Lacage 99c79ebf7e doxygen for Ipv4L4Demux class 2007-03-29 17:43:52 +02:00
Mathieu Lacage 4f3783760b doxygen for Ipv4L4Protocol class 2007-03-29 17:37:51 +02:00
Mathieu Lacage 65ffa3827a doxygen for Ipv4 class 2007-03-29 17:37:39 +02:00
Mathieu Lacage 035a670993 completely document DatagramSocket 2007-03-29 17:23:04 +02:00
Mathieu Lacage adfedc643b document Ipv4Interface completely 2007-03-29 17:17:46 +02:00
Mathieu Lacage 11d19f32e1 document Channel base class 2007-03-29 17:09:16 +02:00
Mathieu Lacage 2584c78959 add NetDevice::GetChannel method and doxygen-document it 2007-03-29 17:07:04 +02:00
Mathieu Lacage f83f28eacc add doxygen doc for missing methopds 2007-03-29 16:55:42 +02:00
Mathieu Lacage a94fb22965 add models to doxygen index 2007-03-29 16:53:34 +02:00
Mathieu Lacage 119eebe3ca change doxygen index for tracing 2007-03-29 16:41:53 +02:00
Mathieu Lacage 3fd6c7d28c index some new features from the main doxygen index 2007-03-29 16:39:40 +02:00
Mathieu Lacage 55d3a13b59 move ValueCDF class to private class member 2007-03-29 16:35:34 +02:00
Mathieu Lacage 467b3d3161 add a randomvariable group 2007-03-29 16:33:28 +02:00
Mathieu Lacage e9ba4fb43c doxygen documentation for ObjectContainer 2007-03-29 16:23:31 +02:00
Mathieu Lacage 3563f218ec forgot to put back TraceResolver in lowleveltracing doxygen group 2007-03-29 15:28:31 +02:00
Mathieu Lacage f4b1b82f47 rework the tracing architecture description 2007-03-29 15:27:39 +02:00
Mathieu Lacage 51d7f89ece fix compilation for optimized builds 2007-03-29 13:24:22 +02:00
Mathieu Lacage 73e6a7aef6 make sure we include std::cout definition even in optimized builds 2007-03-29 13:20:27 +02:00
Unknown 98c97c8047 a point to point ipv4 interface 2007-03-28 19:38:56 +02:00
Unknown da52245cc8 split out AsciiTrace class from simple example 2007-03-28 19:26:58 +02:00
Unknown 6b461f0f8a add packet type logging 2007-03-28 18:33:03 +02:00
Unknown 66b7a217c6 coding style typo 2007-03-28 17:58:17 +02:00
Unknown e51debfab5 work around static initiliazer ordering problem 2007-03-28 17:57:58 +02:00
Unknown 2caa234d78 no need to use compare function directly 2007-03-28 17:52:39 +02:00
Unknown dc1a82772b fix build zith gcc 4.1 2007-03-28 16:48:54 +02:00
Tom Henderson 2d13252e7f One-line bug fix on PointToPointTopology 2007-03-27 23:33:07 -07:00
Tom Henderson 5233780b1c Switch over simple-p2p.cc to use OnOffApplication 2007-03-27 23:14:31 -07:00
Tom Henderson f1cd4984a1 Add ApplicationList and Capability 2007-03-27 21:48:22 -07:00
Craig Dowell 6bf9d35ba8 turn off debug messages 2007-03-27 15:42:17 -07:00
Craig Dowell 6af1c8bb1f net device copy and assignment, reference counted channel. 2007-03-27 15:41:08 -07:00
Craig Dowell 994c7be384 remove unused files, remove notion of PHY, make more realistic p2p-net-device and p2p-channel 2007-03-27 13:04:11 -07:00
Tom Henderson 1a65d66361 A few type changes to not-yet-defined functions 2007-03-26 06:50:33 -07:00
Tom Henderson 3d8f778457 Add net devices to net-device-list in topology 2007-03-26 06:39:20 -07:00
Tom Henderson a3663bc40c Make queues copyable; change p2p-topology.cc to reflect this 2007-03-25 17:47:59 -07:00
Tom Henderson 39d15f6f7e merge in Raj's time changes 2007-03-25 15:35:08 -07:00
Tom Henderson fd92794e43 Move simple-p2p.cc to DataRate; fix small bug in DataRate and add include guards 2007-03-25 15:33:24 -07:00
Unknown be28cb56ff Added back corrected version of TimeUnit(string) 2007-03-25 13:11:20 -04:00
Tom Henderson 8a2cff0607 Add back member variable initializers in p2p-net-device.cc 2007-03-25 07:24:04 -07:00
Tom Henderson c2a49fc1c2 remove 512-byte MTU for P2P net device; make default in base class equal to max uint16 2007-03-25 07:20:24 -07:00
Tom Henderson dd986b3340 Rename classes from Serial to PointToPoint 2007-03-25 07:13:03 -07:00
Tom Henderson 00960518d3 Rename file names from serial to p2p 2007-03-25 06:59:11 -07:00
Tom Henderson f62c2ad8e5 Revert Raj's time unit patch-- causing compilation errors 2007-03-25 06:43:34 -07:00
Raj Bhattacharjea ad941f038c Added TimeUnit<1>::TimeUnit<1>(const std::string&) 2007-03-23 13:47:22 -04:00
Raj Bhattacharjea 4edddaeb2d Added in DataRate to common module 2007-03-22 17:20:15 -04:00
Raj Bhattacharjea 5bb49ff82b RandomVariable API in line with Michelle's comments 2007-03-22 16:41:01 -04:00
Raj Bhattacharjea 3ed3fab322 Fixed accidental hg adding of temp files 2007-03-22 16:02:33 -04:00
George F. Riley 0827230559 Fix compile error mistakenly checked in (Oops!) 2007-03-22 15:06:44 -04:00
George F. Riley 8b9fb7b105 Clean up parameter passing per TOm's request 2007-03-22 14:54:20 -04:00
Raj Bhattacharjea ac13b5523f Fixed major memory bug and docs in RandomVariable 2007-03-22 12:16:10 -04:00
Tom Henderson d52242c4ae OnOffApplication functioning; some Node class cleanup 2007-03-21 23:17:11 -07:00
Tom Henderson 9e86e12f6f Add nodes to NodeList in static Create method; cut over simple-serial.cc to use this node factory 2007-03-20 06:28:24 -07:00
Tom Henderson d456baf82e prepare simple-serial.cc for Node cutover 2007-03-19 22:27:22 -07:00
Tom Henderson 1441c54100 Remove dependency on InternetNode for serial devices 2007-03-19 22:23:16 -07:00
Tom Henderson b9e6974c8e Add static node factory methods to class Node 2007-03-19 22:19:38 -07:00
Tom Henderson a0f6d0c326 Add smartvector, smartset 2007-03-19 21:13:06 -07:00
Tom Henderson 8cc849de4f Move ns-2/simple.cc to examples/simple-serial.cc 2007-03-19 21:01:35 -07:00
Tom Henderson d156b4ab86 Add Mathieu's super object container; add Rx trace on SerialNetDevice 2007-03-19 07:02:14 -07:00
Tom Henderson cd132b39ed Add SerialTopology functions and remove from simple.cc file 2007-03-19 00:40:44 -07:00
Tom Henderson 07cdc040b9 Remove MacAddress from SerialNetDevice constructors, make SerialChannel name argument optional, some trace formatting 2007-03-19 00:21:21 -07:00
Tom Henderson 3e2f129922 Add base class IPAddr; L4Protocol; Protocol; OnOff Application, and base class Socket 2007-03-18 14:35:44 -07:00
Tom Henderson 0689d2c0d7 Begin checkin of ns-3-gfr; s/UdpSocket/DatagramSocket; bring in Application base class and onoff-application, and base class socket; bring in random number generator files 2007-03-18 14:30:26 -07:00
Tom Henderson 327949573d move channel.cc channel.h to node directory; merge ns-3-tracing from mathieu 2007-03-18 14:06:51 -07:00
Mathieu Lacage 79568bde6f ensure iostream is included when doing an optimized build 2007-03-18 19:31:32 +01:00
Tom Henderson 0fad10f942 Make this compile on 32-bit machine; fix SConstruct 2007-03-18 06:25:15 -07:00
Craig Dowell e4f68cc58d serial channel functionality 2007-03-18 03:43:49 -07:00
Tom Henderson 4b39fb88ae Rename UdpSocket to DatagramSocket 2007-03-17 23:16:59 -07:00
Tom Henderson 7868600d6b Add random number files, base class Application 2007-03-17 22:32:08 -07:00
Mathieu Lacage c6bb8b9b64 fix typo. reported by Gustavo Carneiro. 2007-03-15 13:26:30 +01:00
Unknown 6f4566aec7 make sure that there is a C and C++ compiler. Otherwise, we generate large amounts of spurious unrelated errors. 2007-03-14 09:55:35 +01:00
Mathieu Lacage 31adc9851a make TimeUnit<1>.GetSeconds() work, and similar for scalars. Patch by Gustavo Carneiro. 2007-03-13 17:44:36 +01:00
Tom Henderson c2460c024a Rename simple.tcl.cc to simple.cc; remove OTcl comments 2007-03-07 22:45:17 -08:00
Tom Henderson e7e003521d Fix bug 8: Enque/Deque misspelled 2007-03-07 22:26:20 -08:00
Mathieu Lacage 7d3e9538f0 add consistency checks. Based on patch by Gustavo Carneiro 2007-03-06 18:38:51 +01:00
Mathieu Lacage c276aab07b add operator = to InternetNode 2007-02-26 10:28:57 +01:00
Mathieu Lacage 796b5d4a3f move serial code to src/devices/serial 2007-02-22 10:04:54 +01:00
Mathieu Lacage e69f129532 remove unused header 2007-02-22 10:03:55 +01:00
Mathieu Lacage 1a279cc652 remove unused files 2007-02-22 09:54:27 +01:00
Mathieu Lacage f099a24c94 move p2p to new dir 2007-02-22 09:51:54 +01:00
Mathieu Lacage 2218e346ae merge with trunk 2007-02-22 09:40:46 +01:00
Mathieu Lacage 2a994cb96e merge with trunk 2007-02-22 09:40:41 +01:00
Mathieu Lacage f07316cd2c add some simple packet content dumping. 2007-02-21 23:09:42 +01:00
Unknown ac25315862 Add DEBUG to ipv4-address.cc 2007-02-21 12:52:35 -08:00
Mathieu Lacage b95ce71aaf make trailing ';' mandatory for NS_ASSERT* and NS_FATAL_ERROR macros. fix uses. 2007-02-21 20:07:39 +01:00
Mathieu Lacage 29b2db3a67 make trailing ';' mandatory with NS_DEBUG macros. fix all invalid uses. 2007-02-21 20:04:32 +01:00
Mathieu Lacage a9d2b13fa1 avoid dumping the first packet 2007-02-21 18:28:25 +01:00
Mathieu Lacage 904c8f5a8a improve arp debugging output 2007-02-21 18:14:03 +01:00
Mathieu Lacage 62ff2e87b3 fix coding style 2007-02-21 17:58:14 +01:00
Mathieu Lacage b3e2607291 make the multiple-queue tracing case work 2007-02-21 17:55:14 +01:00
Mathieu Lacage 6efb114f27 connect to simple queue event names. 2007-02-21 17:46:40 +01:00
Mathieu Lacage 76322a79de fix queue tracing 2007-02-21 17:06:19 +01:00
Unknown 390d3d8089 Remove netmask from AddDuplexLink signature 2007-02-21 07:37:44 -08:00
Mathieu Lacage d2064f1190 remove now-unused call to c_str () 2007-02-21 16:30:08 +01:00
Mathieu Lacage 234b1490cb replace char const * with std::string const & 2007-02-21 16:27:42 +01:00
Unknown f6e33b54b7 trace files should not be opened for appending 2007-02-21 06:42:58 -08:00
Unknown 82e86038c1 touch a file 2007-02-21 01:37:00 -08:00
Unknown 379e7ffd5f Forgot to add in serial-phy classes 2007-02-21 00:15:47 -08:00
Unknown 97af81500b Plumbing in SerialPhy in receive direction 2007-02-21 00:09:28 -08:00
Unknown a8a939e65e Move a few functions definitions out of headers 2007-02-21 00:02:27 -08:00
Unknown cc8286b25e Plumb in outbound SerialPhy 2007-02-20 23:58:21 -08:00
Unknown c320f9ea81 Skeleton SerialPhy 2007-02-20 23:26:59 -08:00
Unknown 0523df8827 Added tracing support to simple.tcl.cc (Craig) 2007-02-20 22:55:09 -08:00
Mathieu Lacage ac3a5df3b5 fix routing table configuration 2007-02-19 12:22:20 +01:00
Mathieu Lacage 76311fe551 bind sinks to port 80 2007-02-19 11:39:27 +01:00
Mathieu Lacage 6c7109309f do not generate zero-sized packets 2007-02-19 10:52:04 +01:00
Mathieu Lacage 3326fdba35 use new NS_ASSERT macro rather than assert. this makes the code build on my machine. 2007-02-19 10:23:50 +01:00
Tom Henderson 847aca86cf Added all UDP sources, sinks, routes-- not working yet 2007-02-19 00:44:05 -08:00
Tom Henderson 17a41557f2 Add UdpSockets to simple.tcl.cc 2007-02-19 00:00:49 -08:00
Tom Henderson f0d12b6e81 Enhanced AddDuplexLink() 2007-02-18 23:29:05 -08:00
Craig Dowell f0793fbae6 turn off debug prints 2007-02-18 19:25:53 -08:00
Unknown 957462263f strawman connectors and channel 2007-02-18 19:19:42 -08:00
Mathieu Lacage 848e50c5b5 convert to new debug macros 2007-02-18 11:22:23 +01:00
Mathieu Lacage 715c72fac2 convert to new debug macros 2007-02-18 11:19:58 +01:00
Mathieu Lacage d7efedefde merge tom's tree with trunk 2007-02-18 11:16:08 +01:00
Tom Henderson 114c1a93d2 Merge in Craig's tracing changes as of Thursday; rename net-device-serial files to serial-net-device 2007-02-17 16:40:03 -08:00
Mathieu Lacage c2e3d19e06 remove UdpIpv4L4Protocol class 2007-02-17 09:42:30 +01:00
Mathieu Lacage d7a398bc11 remove ArpL3Protocol object 2007-02-17 09:35:50 +01:00
Mathieu Lacage e4166af294 remove Ipv4L3Protocol class. 2007-02-17 09:28:02 +01:00
Mathieu Lacage 873bbd4ba1 convert old TRACE code to use new NS_DEBUG macro 2007-02-16 10:04:02 +01:00
Mathieu Lacage d9318db068 convert use of <cassert> to "ns3/assert.h" 2007-02-16 09:56:21 +01:00
Mathieu Lacage 342ada342a preprecessor typo 2007-02-16 09:42:53 +01:00
Mathieu Lacage 7f5d4a1a79 remove extra debug.cc from build 2007-02-16 09:40:19 +01:00
Mathieu Lacage 2fafcce00c call NS_DEBUG_COMPONENT_DEFINE when needed 2007-02-16 09:37:35 +01:00
Mathieu Lacage 9e99f617ec convert NS3_TRACEALL to NS_DEBUG_UNCOND 2007-02-16 09:35:01 +01:00
Mathieu Lacage f2533a7645 convert NS3_TRACE to NS_DEBUG 2007-02-16 09:34:28 +01:00
Mathieu Lacage a49fb6556a merge with debug tree 2007-02-16 09:32:02 +01:00
Mathieu Lacage ded5b872b9 add NS_DEBUG_UNCOND 2007-02-16 09:26:56 +01:00
Mathieu Lacage 07b9fc12aa add fatal-error.h header 2007-02-16 09:23:22 +01:00
Mathieu Lacage 8cf0f1f4b4 make sure that NS3_ASSER_ENABLE is defined in debug builds 2007-02-16 09:23:13 +01:00
Mathieu Lacage 50a1e7d737 split out assert from debug.h 2007-02-16 09:00:22 +01:00
Tom Henderson 421fe63583 large checkin-- bringing in serial device code 2007-02-15 23:55:15 -08:00
Tom Henderson ff0432af99 Add InternetNode() 2007-02-15 22:27:33 -08:00
Tom Henderson 69f8408b04 Add Simulator::StopAt() 2007-02-15 21:56:24 -08:00
Tom Henderson db2795f4b1 Add samples/ns-2/simple.tcl.cc to SConstruct 2007-02-15 21:54:16 -08:00
Unknown 95f07a831b queues, trace-writer, debug 2007-02-15 16:52:39 -08:00
Tom Henderson 465c2daa6b Test of commit access with Mercurial cheat sheet 2007-02-14 22:04:38 -08:00
Mathieu Lacage 06788bac27 regex: s/NS3_/NS_/ 2007-02-13 18:20:24 +01:00
Mathieu Lacage 42ea8aabe0 add API doc 2007-02-13 10:23:47 +01:00
Mathieu Lacage b2c8866cbf make sure tha NS3_DEBUG_ENABLE is defined by doxygen preprocessor 2007-02-13 10:23:31 +01:00
Mathieu Lacage 310f67b835 avoid warning in optimized builds 2007-02-13 10:23:10 +01:00
Mathieu Lacage cb102a5d0b improve assert brekapoint function 2007-02-13 10:22:49 +01:00
Mathieu Lacage f5fee4c7af really trigger segfault when needed 2007-02-13 09:52:42 +01:00
Mathieu Lacage bd19595461 add NS3_ASSERT and NS3_ASSERT_MSG 2007-02-13 09:45:32 +01:00
Mathieu Lacage 604f7b13e7 change defaults to be a bit more reasonable 2007-02-12 23:46:53 +01:00
Mathieu Lacage f4617ef46a make trace version build 2007-02-12 23:46:40 +01:00
Mathieu Lacage 53ed89a9e0 initialize correctly mac addresses read from arp packets 2007-02-12 23:37:15 +01:00
Mathieu Lacage e63da149b5 configure the ipv4 interfaces 2007-02-12 23:24:20 +01:00
Mathieu Lacage ed1e87c051 make sure that mac addr len is correctly written 2007-02-12 23:24:00 +01:00
Mathieu Lacage fdae8028d6 make sure the MTU is correcrtly setup and the link is up. 2007-02-12 23:23:30 +01:00
Mathieu Lacage c76a89d22a replace pointer with reference 2007-02-12 23:22:48 +01:00
Mathieu Lacage 3d32a4d0d2 add routing table output function 2007-02-12 22:44:41 +01:00
Mathieu Lacage 608862b8d2 make route iteration actually work 2007-02-12 22:44:18 +01:00
Mathieu Lacage df35898657 make the p2p example compile 2007-02-12 20:15:19 +01:00
Mathieu Lacage 380b55a1f1 small typo 2007-02-12 20:15:08 +01:00
Mathieu Lacage ef8e255fd9 make rx work by upping the interface once it is ready 2007-02-12 19:58:10 +01:00
Mathieu Lacage 5f559b47f8 make simple example work 2007-02-12 19:52:01 +01:00
Mathieu Lacage da3bdd9824 add some traffic generation to sample code 2007-02-12 19:47:36 +01:00
Mathieu Lacage 12cf66da2b fix memory leaks for simple sample code 2007-02-12 19:32:42 +01:00
Mathieu Lacage 5b05f21261 make the sample code compile and link. 2007-02-12 19:28:48 +01:00
Mathieu Lacage 85025db6dd implement ipv4 loopback for testing 2007-02-12 19:28:19 +01:00
Mathieu Lacage 3c434977f0 add p2p netdevice and channel 2007-02-12 16:45:58 +01:00
Mathieu Lacage 8c31ac1950 remove SetNodeId and implement GetId and GetSystemId 2007-02-12 16:01:18 +01:00
Mathieu Lacage 5d68fb13ea do not include dead header 2007-02-12 16:01:07 +01:00
Mathieu Lacage 9a899b14b1 add arp stack 2007-02-12 15:55:49 +01:00
Mathieu Lacage ea343befaf add Ipv4 and Udp node capabilities, rework Copy methods to include an extra Node * argument 2007-02-12 13:06:05 +01:00
Mathieu Lacage 96d809c983 add non-debugged udp stack 2007-02-10 11:29:44 +01:00
Mathieu Lacage ec6e1ff8bc add packet constructor which accepts payload buffer. 2007-02-10 10:24:36 +01:00
Mathieu Lacage 1df1c2d0c2 add start of udp stack 2007-02-09 19:40:19 +01:00
Mathieu Lacage 738a39cc0d make Send method public 2007-02-09 19:40:12 +01:00
Mathieu Lacage 758963eff5 a basic untested ipv4 implementation 2007-02-09 17:54:49 +01:00
Mathieu Lacage 70e5b37f4f add ipv4 and udp header, add ipv4 checksum support to make the udp header compile. Need to be fixed in UdpHeader later. 2007-02-08 16:01:58 +01:00
Mathieu Lacage 9609fe68f0 code from all trees. 2007-02-08 15:37:48 +01:00
Mathieu Lacage e73ac88cf2 change emacs style commands 2007-02-08 11:13:49 +01:00
Mathieu Lacage 0d9305c70a initial node base class from george's repo. 2007-02-08 11:11:24 +01:00
Mathieu Lacage 7abd854183 test and debug the debug support 2007-02-07 08:49:54 +01:00
Mathieu Lacage 95778d9453 define NS3_DEBBUG_ENABLE when needed 2007-02-07 08:29:01 +01:00
Mathieu Lacage 8cfa657d89 remove EnableEnvVar function 2007-02-06 21:42:31 +01:00
Mathieu Lacage 84bdfa4ac5 add debugging support 2007-02-06 20:40:38 +01:00
Mathieu Lacage 7de56dad44 remove compiler warning about unused variable when asserts are disabled. 2007-02-06 19:59:28 +01:00
Mathieu Lacage 02d1e1f2e9 merge from trunnk 2007-02-06 15:50:20 +01:00
Mathieu Lacage 1cc14d25dc avoid unused variable compiler warnings 2007-02-06 15:49:42 +01:00
Mathieu Lacage 392e51924b merge with ns-3-ptr branch 2007-02-06 08:57:44 +01:00
Mathieu Lacage 4094a5bb2c handle correctly nanosecond input 2007-02-05 12:42:32 +01:00
Mathieu Lacage 9df3f18084 use the new CallbackTracerBase::CheckCallbackType method to ensure proper type matching when invoking TraceContainer::SetCallback 2007-02-05 12:42:16 +01:00
Mathieu Lacage bcad837abd add CallbackTracerBase and CallbackTracerBase::CheckCallbackType method to check the runtime type of a CallbackTracer 2007-02-05 12:41:36 +01:00
Mathieu Lacage 37b5380332 add CallbackBase and CallbackImplBase to allow the implementation of the runtime type checking method Callback::ChekType 2007-02-05 12:39:51 +01:00
Mathieu Lacage d876bcc5ec constify 2007-02-05 12:38:52 +01:00
Unknown a32774f7c9 Raj test commit 2007-02-02 14:41:28 -05:00
Mathieu Lacage fe5bf44c65 add implementation comment 2007-02-02 20:02:34 +01:00
Mathieu Lacage 2e4ee67fea optimize Time::Get methods 2007-02-02 19:40:03 +01:00
Mathieu Lacage 48ae43c61e optimize Time arithmetic operations. 2007-02-02 19:37:16 +01:00
Mathieu Lacage 57b398139b fix trace output 2007-02-02 19:29:55 +01:00
Mathieu Lacage 548b20f75a added useless Time::Seconds method when doing testing for the removal of the Seconds class. Remove it. 2007-02-02 19:14:16 +01:00
Mathieu Lacage 99848bfcd9 add a few more tests for the Time class 2007-02-02 15:39:47 +01:00
Tom Henderson 9665e33445 Initial simple.tcl file 2007-02-02 00:04:48 -08:00
Mathieu Lacage 19e32b1d0c fix EventId::IsExpired and Simulator::IsExpired, add EventId::IsRunning, add relevant tests, replace Seconds, MilliSeconds, MicroSeconds, and, NanoSeconds classes by functions named similarly 2007-02-01 18:52:55 +01:00
Mathieu Lacage 8ef4881f88 Make tags more robust with regard to lack of tag registration 2007-02-01 18:50:58 +01:00
Mathieu Lacage 6bb4175d83 allow you to specify extra link flags for each module 2007-02-01 18:50:19 +01:00
Mathieu Lacage 041fcd1752 add ns3::Ptr<T>::operator * with a few tests 2007-01-31 20:14:23 +01:00
Mathieu Lacage b37a9d44e8 add smart pointer sample code 2006-12-22 09:03:09 +01:00
Mathieu Lacage 735a076eb3 more tests, fix bugs uncovered by tests 2006-12-18 14:25:33 +01:00
Mathieu Lacage 3a88bb5f32 smart pointer tests. no bugs for now 2006-12-18 13:28:29 +01:00
Mathieu Lacage 4c0c225a19 initial go at smart pointer implementation 2006-12-18 13:17:08 +01:00
Mathieu Lacage 8138e1f91c make Heap scheduler remove operation first perform a linear search to find the target location and then perform a correct remove through a top-down heapification 2006-12-18 11:39:48 +01:00
Mathieu Lacage 05852215dc make sure we reset the simulator configuration for each run 2006-12-15 13:51:56 +01:00
Mathieu Lacage 311c6ce026 add command-line options to simulator benchmark 2006-12-15 10:19:49 +01:00
Mathieu Lacage fb50c9bf5e remove now unused internal iterator from EventImpl class 2006-12-15 10:08:22 +01:00
Mathieu Lacage a9e5c1ee3a remove empty tests 2006-12-15 10:06:55 +01:00
Mathieu Lacage e28e55aea8 make the event replay code actually work. Stop using deques and use std::vector instead. plus a bunch of other fixes to deal correctly with removes 2006-12-15 10:05:28 +01:00
Mathieu Lacage 6aa35066f2 We need to make sure that the uid of the first event generated is different from the uid of the simulator when no events have yet been run. 2006-12-15 10:01:23 +01:00
Mathieu Lacage 3cab375630 allow the user to specify microseconds and nanoseconds in 64bit units. 2006-12-13 15:20:03 +01:00
Mathieu Lacage 9052010557 Log format is defined in units of nano seconds rather than seconds. 2006-12-13 15:19:06 +01:00
Mathieu Lacage bdc613c1df fix the Simulation event replayer: make it build 2006-12-12 14:59:13 +01:00
Mathieu Lacage 262d09de55 optmize std::map comparison 2006-12-12 14:41:52 +01:00
Mathieu Lacage 6e0bc0ef9b optmize binary heap comparison 2006-12-12 14:41:39 +01:00
Mathieu Lacage 873367522a optimize other all comparison operators 2006-12-12 14:31:16 +01:00
Mathieu Lacage cd7c70b0a1 optimize Binary Heap comparison operator 2006-12-12 14:30:44 +01:00
Mathieu Lacage 671b1cdf4e fix warnings for optimized build 2006-12-12 14:17:00 +01:00
Mathieu Lacage 19d2e21aaf add small perl utility to generate static sample distributions 2006-12-12 14:02:07 +01:00
Mathieu Lacage 3473e1cb60 fix coding style 2006-12-12 13:53:30 +01:00
Mathieu Lacage b34af189e6 add help output to simulator bench/tester 2006-12-12 13:50:35 +01:00
Mathieu Lacage 3fb6ed332a add empty binary heap test 2006-12-11 19:43:46 +01:00
Mathieu Lacage 2fe5076375 remove now-unimplemented IsValid method 2006-12-11 19:37:53 +01:00
Mathieu Lacage 394c26b05b make SchedulerHeap not use the internal iterator void * 2006-12-11 19:36:48 +01:00
Mathieu Lacage 0dacd8bfda do not use internal iterator void *. fix valgrind warnings 2006-12-11 19:14:38 +01:00
Mathieu Lacage a29dd08cd0 std::map::find triggers this assert on purpose. So, the assert is wrong. 2006-12-11 19:14:24 +01:00
Mathieu Lacage 5540a3de6d do not forget to update the key arg upon sucessful return 2006-12-11 19:13:35 +01:00
Mathieu Lacage c2a68da13e do not use internal iterator void * pointer in SchedulerList 2006-12-11 19:07:25 +01:00
Mathieu Lacage dcd8c74ae8 fix memory leaks 2006-12-11 18:56:11 +01:00
Mathieu Lacage 7d8437b78f remove purity from virtual destructor in Header and Trailer 2006-12-05 10:08:27 +01:00
Mathieu Lacage 5993280585 merge 2006-12-04 13:51:42 +01:00
Mathieu Lacage 776392cee4 even more tests 2006-12-04 13:49:28 +01:00
Mathieu Lacage 25fa4c6c83 a bunch of tests 2006-12-04 13:45:46 +01:00
Mathieu Lacage 40c7810080 more tests for Time class 2006-12-04 13:42:31 +01:00
Mathieu Lacage ad9f80c1c5 improve the precision of the multiplication operator 2006-12-04 13:25:51 +01:00
Mathieu Lacage b6acf05f80 fix 128 bit to/from double conversions 2006-12-04 12:51:57 +01:00
Mathieu Lacage a912bad39d add dep on math library 2006-12-04 12:33:54 +01:00
Mathieu Lacage 5d99ccd05a fix div and mul operators 2006-12-04 11:04:49 +01:00
Mathieu Lacage 90d2fc50e9 make sure cairo internal header is installed when needed. 2006-12-04 10:34:02 +01:00
Mathieu Lacage 16e62faea8 implement 128 bit arithmetic with cairo's internal types 2006-12-04 10:33:02 +01:00
Mathieu Lacage 54003d6fd0 fix typo and make sure we use uint64 native type by default. 2006-12-04 10:17:53 +01:00
Mathieu Lacage d9485fce89 split high precision implementations in different files 2006-12-04 08:39:11 +01:00
Mathieu Lacage 8e928e75e4 fix some warnings 2006-12-04 08:11:44 +01:00
Mathieu Lacage 0018ebb50b fix obvious bugs in some cairo exotic functions 2006-12-04 08:05:34 +01:00
Mathieu Lacage 04e6f0dfa0 add needed configure magic and header includes 2006-12-04 08:03:28 +01:00
Mathieu Lacage fa04c0e0df import cairo code 2006-12-04 07:33:45 +01:00
Mathieu Lacage ac043f3e9d rename Time::ApproximateTo methods to Time::Get 2006-11-21 15:53:32 +01:00
Mathieu Lacage b4e41a481b make Time relative instead of Absolute 2006-11-21 15:50:09 +01:00
Mathieu Lacage a499791366 patch to build documentation from paul@cravenfamily.com 2006-11-16 12:04:36 +01:00
Mathieu Lacage 48c5381ac1 add documentation for the inheritenv option 2006-11-06 14:25:35 +01:00
Mathieu Lacage bb29989cac obey inheritenv variable on scons command-line (patch from Gustavo Carneiro) 2006-11-06 14:23:58 +01:00
Mathieu Lacage 9593f026a9 more tests for Time classes 2006-11-03 11:07:24 +01:00
Mathieu Lacage 13b6868242 fix Simulator doxygen warnings 2006-11-03 10:22:55 +01:00
Mathieu Lacage 7c28f1cf7b add doxygen dox for Time classes 2006-11-03 10:22:45 +01:00
Mathieu Lacage a0a93e6f8d implement Scalar::GetDouble 2006-11-03 09:28:29 +01:00
Mathieu Lacage c4084caf1e add a bunch of tests for Time classes 2006-11-03 09:26:48 +01:00
Mathieu Lacage a4b9296639 new Time implementation 2006-11-03 09:22:07 +01:00
Mathieu Lacage 3cd499c1a7 add Abs/Max/Min non-member functions 2006-11-03 09:17:13 +01:00
Mathieu Lacage 4c969e8fbe add ns3 namespace to HighPrecision class 2006-11-03 09:07:43 +01:00
Mathieu Lacage e24d630008 Add HighPrecision class used for external Time bookkeeping 2006-11-03 09:05:58 +01:00
Mathieu Lacage 72d9b91ce5 fix python indent. 2006-11-03 09:04:12 +01:00
Mathieu Lacage aa2ba3ea27 add Scale/Min/Max/Abs non-member functions 2006-11-01 13:27:32 +01:00
Mathieu Lacage 0fade9d7af fix coding style 2006-11-01 13:11:30 +01:00
Mathieu Lacage 5a2a57e052 merge 2006-11-01 13:00:34 +01:00
Mathieu Lacage fbdca3413b make coding style two space indent 2006-10-28 21:32:17 +02:00
Mathieu Lacage a958188e19 fix build 2006-10-28 21:25:00 +02:00
Mathieu Lacage fecf0c1494 implement ScheduleNow and ScheduleDestroy methods 2006-10-28 21:21:55 +02:00
Mathieu Lacage ebd16ea6fc implement overloads for ScheduleNow and ScheduleDestroy 2006-10-28 21:21:53 +02:00
Mathieu Lacage 35eab87f76 start of work to re-implement Schedule* methods 2006-10-28 21:21:51 +02:00
Mathieu Lacage ef639a6e17 fix Time::ApproximateTo* return type 2006-10-28 21:21:48 +02:00
Mathieu Lacage 4449e8b51d new Time implementation 2006-10-28 21:21:34 +02:00
Mathieu Lacage ab50c87bf2 move event generation to MakeEvent methods 2006-10-28 17:44:15 +02:00
Mathieu Lacage 099633a180 import RPATH handling on posix systems. Based on patch by Nicola Baldo <baldo@dei.unipd.it> 2006-10-23 15:21:31 +02:00
Mathieu Lacage 7f101b2f41 make python code more Pep8 conformant (patch from Gustavo Carneiro) 2006-10-23 09:24:36 +02:00
Mathieu Lacage defa1e3a91 fix coding style 2006-10-21 11:35:34 +02:00
Mathieu Lacage df7747bbe6 fix coding style 2006-10-21 11:35:02 +02:00
Mathieu Lacage 7ea80521bb fix coding style 2006-10-20 15:09:24 +02:00
Mathieu Lacage 676dc8b5ac fix coding style 2006-10-20 14:21:33 +02:00
Mathieu Lacage 90df8d054b change emacs mode to new NS3 elisp mode 2006-10-20 14:17:03 +02:00
Mathieu Lacage b89772f06b merge 2006-10-20 14:10:10 +02:00
Mathieu Lacage ac4aeaca3d fix coding style 2006-10-18 09:27:21 +02:00
Mathieu Lacage a535e12b9e fix python tab indent 2006-10-16 13:12:22 +02:00
Tom Henderson f0b9b4c165 apply python changes 2006-10-14 16:43:21 -07:00
Mathieu Lacage 504d4ad8bd add magic emacs incantation for python 2006-10-14 10:13:14 +02:00
Tom Henderson 174843047b remove reference to Chunk class 2006-10-13 13:07:45 -07:00
Tom Henderson 4eda06b7e8 a few wordsmithing changes 2006-10-13 13:07:23 -07:00
Mathieu Lacage 9e4cfc42bf improve the IsExpired documentation 2006-10-06 20:17:53 +02:00
Mathieu Lacage 7f8eb2c50b fix coding style 2006-10-06 13:37:25 +02:00
Unknown 729c3f373b remove unused variable 2006-10-03 12:21:13 +02:00
Unknown cf41608a09 make destructor public to avoid compiler warning. 2006-10-03 12:20:13 +02:00
Unknown 17233b9d8b fix 64 bit warning 2006-10-03 12:18:53 +02:00
Mathieu Lacage 6e9a43cb92 document gcov/lcov targets 2006-10-03 10:48:23 +02:00
Mathieu Lacage 7937fef2f7 fix lcov report output 2006-10-03 10:45:39 +02:00
Mathieu Lacage c3a9fb96d2 add lcov support 2006-10-03 10:20:55 +02:00
Mathieu Lacage 3d64c8d0b6 allow the user to provide project-wide compilation and link flags 2006-10-03 08:17:05 +02:00
Mathieu Lacage 77b66f56e1 test each default event scheduler 2006-10-02 19:10:04 +02:00
Mathieu Lacage bc51c0576c tweak doxygen output 2006-10-02 14:45:43 +02:00
Mathieu Lacage f4c2f82da9 remove reference to Chunk 2006-10-02 14:41:00 +02:00
Mathieu Lacage bbcf953d34 try to get rid of tabs which sneaked in 2006-10-02 14:37:46 +02:00
Mathieu Lacage 9f93b7fb53 fix emacs tab mode (reported by george) 2006-10-02 14:34:53 +02:00
Mathieu Lacage a405ffd68d add Simulator::enableParallelSimulation method 2006-10-02 11:43:54 +02:00
Mathieu Lacage a1f245126e rename time.h to nstime.h 2006-10-02 11:41:40 +02:00
Mathieu Lacage 21039d13d2 add trailer 2006-10-02 11:39:45 +02:00
Mathieu Lacage a11e85066f remove chunk 2006-10-02 11:32:31 +02:00
Mathieu Lacage 4cabbc027a small doc fix 2006-10-02 11:25:07 +02:00
Mathieu Lacage 4809217dc0 add header 2006-10-02 11:23:18 +02:00
Mathieu Lacage 4d69c43531 fix typo 2006-09-30 08:04:37 +02:00
Mathieu Lacage 4ef43ab1c8 rename Chunk::print to Chunk::printTo 2006-09-30 08:03:40 +02:00
Mathieu Lacage eb94e8ca83 add documentation on build system 2006-09-30 07:59:37 +02:00
Mathieu Lacage 049eb78586 change Time into Time const & 2006-09-29 19:18:48 +02:00
Mathieu Lacage 797df745cd merge 2006-09-28 10:11:09 +02:00
Mathieu Lacage af72e72dc7 fix build for optimized case 2006-09-25 19:02:13 +02:00
Mathieu Lacage fecc1ded2a add Constants section to doxygen documentation 2006-09-25 18:55:23 +02:00
Mathieu Lacage 90235f36b8 test of cron email setup 2006-09-20 20:14:47 +02:00
Mathieu Lacage d663c4a254 test 2 of emails 2006-09-20 20:12:18 +02:00
Mathieu Lacage 6892171fee test of emails 2006-09-20 20:07:46 +02:00
Mathieu Lacage bd97522a7c implement new tag identification scheme 2006-09-15 13:05:03 +02:00
Mathieu Lacage 3e88c0eb3a document packet uid, fix build 2006-09-08 18:57:40 +02:00
Mathieu Lacage b61c5a3a18 add packet uid 2006-09-08 18:51:47 +02:00
Mathieu Lacage 1a510b4a26 replace pointers with references 2006-09-08 18:45:48 +02:00
Mathieu Lacage 40dac3634e fix distcheck 2006-09-08 09:20:17 +02:00
Mathieu Lacage bc2dfd243a add comment on rpath 2006-09-08 09:18:33 +02:00
Mathieu Lacage 40b66b8383 beautify build instructions 2006-09-08 09:16:52 +02:00
Mathieu Lacage 7be84aded8 move around code to implementation section 2006-09-07 12:35:06 +02:00
Mathieu Lacage c6e4b8811d doc typo 2006-09-07 12:34:53 +02:00
Mathieu Lacage 0aeb4faa87 integrate sample code 2006-09-07 11:15:40 +02:00
Mathieu Lacage 54649b315a add inria copyright and gpl statement on build.py 2006-09-07 11:03:04 +02:00
Mathieu Lacage d13d83d81a fix doc typo 2006-09-07 10:51:12 +02:00
Mathieu Lacage 842015ef19 add high-level intro to Packet API and implementation 2006-09-07 10:12:40 +02:00
Mathieu Lacage d0f62fbb87 start of rationale for packets 2006-09-06 17:06:45 +02:00
Mathieu Lacage 4fa19c35b5 improve documentation and remove updateTag method 2006-09-06 16:46:26 +02:00
Mathieu Lacage fede074f3a add comment on implementation location 2006-09-06 15:20:25 +02:00
Mathieu Lacage 73b1489fbc add comment on implementation location 2006-09-06 15:19:03 +02:00
Mathieu Lacage 48200e2976 add comment on implementation location 2006-09-06 15:18:20 +02:00
Mathieu Lacage 51cea233f1 reorganize the implementation of template member methods in Simulator class 2006-09-06 15:17:44 +02:00
Mathieu Lacage 71426c90f9 fix documentation generation warning and add doc for TagPrettyPrinter 2006-09-06 15:01:56 +02:00
Mathieu Lacage 2f85a9e691 move aroudn bound functors 2006-09-06 14:56:13 +02:00
Mathieu Lacage a129ff2a7d add scheduler example reference 2006-09-06 14:53:11 +02:00
Mathieu Lacage 501829319e document the fact that it is impossible to unschedule event scheduled for the "destroy" time 2006-09-06 14:51:50 +02:00
Mathieu Lacage 0364386fa7 document EventId 2006-09-06 14:46:09 +02:00
Mathieu Lacage 16602f09c4 add missing documentation in simulator class 2006-09-06 14:35:40 +02:00
Mathieu Lacage 8602baa246 document Time class 2006-09-06 14:18:37 +02:00
Mathieu Lacage a10eccf11f remove unused code 2006-09-06 14:08:19 +02:00
Mathieu Lacage db1ffacc10 fix typo 2006-09-06 14:08:13 +02:00
Mathieu Lacage 55fe398822 fix test sample code 2006-09-06 14:06:04 +02:00
Mathieu Lacage 8e10651026 make sure RUN_SELF_TESTS macro is defined when preprocessing for doxygen 2006-09-06 14:04:03 +02:00
Mathieu Lacage fc294f6e01 comment a bit the sample code 2006-09-06 14:03:39 +02:00
Mathieu Lacage f22af44dd1 split SConstruct to make it more readable 2006-09-06 13:59:43 +02:00
Mathieu Lacage f19b51afe0 rename sample binaries 2006-09-06 13:36:34 +02:00
Mathieu Lacage 495c246850 add sample code for test, add doxygen doc 2006-09-06 13:35:23 +02:00
Mathieu Lacage 9f1957be9d fix doxygen typos 2006-09-06 13:34:58 +02:00
Mathieu Lacage 5f560144b7 more ignore files 2006-09-06 13:21:45 +02:00
Mathieu Lacage 653fcde142 add doc target to BUILD file 2006-09-06 11:26:51 +02:00
Mathieu Lacage 12c001afe7 add doc target for doxygen build 2006-09-05 15:55:04 +02:00
Mathieu Lacage 36dc7c5b99 add doxygen framework 2006-09-05 13:42:32 +02:00
Mathieu Lacage f935fe02bd change indent to be 4 spaces 2006-09-05 13:18:11 +02:00
Mathieu Lacage e57dd3faa5 variable/method/function coding style update 2006-09-05 13:13:39 +02:00
Mathieu Lacage 778ca40af3 member variables coding style change 2006-09-05 12:54:53 +02:00
Mathieu Lacage 2329966acc remove unused file 2006-09-05 11:23:39 +02:00
Mathieu Lacage dacf6d146c reorder files 2006-09-05 11:22:13 +02:00
Mathieu Lacage fc15c8d04d remove unused file 2006-09-05 11:21:32 +02:00
Mathieu Lacage f811daf33b merge 2006-09-05 11:16:08 +02:00
Mathieu Lacage 57880bc9da add documentation for scheduler factory 2006-09-04 15:52:45 +02:00
Mathieu Lacage 1ebee07e78 cleanup the Scheduler API 2006-09-04 15:37:32 +02:00
Mathieu Lacage 1cfa43cf3b enable user-provided schedulers 2006-09-04 15:24:05 +02:00
Mathieu Lacage 5b02e3bc1b rename files 2006-09-04 15:09:58 +02:00
Mathieu Lacage 62e1051d4c rename TracedVariable to VariableTracer 2006-09-04 15:06:09 +02:00
Mathieu Lacage 05cbced73d rename trace stream to stream tracer 2006-09-04 14:10:34 +02:00
Mathieu Lacage 00d7f1810c rename callback logger to callback tracer 2006-09-04 14:06:00 +02:00
Mathieu Lacage f9a13fdbfd remove packet logger. replace it with more generic callback logger 2006-09-04 13:40:02 +02:00
Mathieu Lacage 70be235d03 add comment on unused code 2006-09-04 13:19:07 +02:00
Mathieu Lacage 79ba177ba4 fix us/ns handling 2006-09-04 13:18:16 +02:00
Mathieu Lacage d6048b8a61 improve tests 2006-09-04 13:14:39 +02:00
Mathieu Lacage a222d1b8da use ns as internal time and export time as ns. 2006-09-04 13:11:34 +02:00
Mathieu Lacage b77c4b2bdd remove extra code 2006-09-04 12:51:11 +02:00
Mathieu Lacage 554cb205f4 remove more unused files, rename system files 2006-09-04 12:28:04 +02:00
Mathieu Lacage 0e8ba3a194 remove unused system files 2006-09-04 12:23:44 +02:00
Mathieu Lacage 67064f85dc more tests 2006-09-03 15:17:01 +02:00
Mathieu Lacage aac8571003 add simulator tests 2006-09-03 15:13:56 +02:00
Mathieu Lacage ac62098a81 add empty simulator test 2006-09-03 12:49:47 +02:00
Mathieu Lacage b335fe1455 remove dead code 2006-09-03 12:44:49 +02:00
Mathieu Lacage e5a94ff402 test 1 arg version for member ptrs 2006-09-03 12:43:09 +02:00
Mathieu Lacage a8ece76eac param order was inverted 2006-09-03 12:43:00 +02:00
Mathieu Lacage 6f7c87a070 add multiple argument versions 2006-09-03 12:40:19 +02:00
Mathieu Lacage 02fa792b81 first cut at george's ideas on api 2006-09-03 12:24:04 +02:00
Mathieu Lacage fd43aa8bdf doc typo 2006-09-02 19:50:19 +02:00
Mathieu Lacage 490a08af92 fix build 2006-09-02 12:13:22 +02:00
Mathieu Lacage 2097de0a7e rename run_serial to run 2006-09-02 12:09:59 +02:00
Mathieu Lacage cb8352f9c2 remove parallel queues 2006-09-02 12:09:07 +02:00
Mathieu Lacage a525ec46e5 small formatting detail 2006-08-29 18:28:45 +02:00
Mathieu Lacage 5ffcea26af use rpath only on posix platforms 2006-08-29 18:27:42 +02:00
Mathieu Lacage 56f3965e91 compile these classes for darwin 2006-08-29 18:23:19 +02:00
Mathieu Lacage 0ad28e0595 build instructions 2006-08-29 18:08:51 +02:00
Mathieu Lacage 28c0b86278 change yans namespace to ns3 2006-08-29 17:55:34 +02:00
Mathieu Lacage 37eabeed61 remove sgi-hashmap.h 2006-08-29 17:51:31 +02:00
Mathieu Lacage e54c17ecd7 replace yans include with ns3 include 2006-08-29 17:51:04 +02:00
Mathieu Lacage 344fe9eb0a remove dead files 2006-08-29 17:48:43 +02:00
Mathieu Lacage a95a257ae9 utils and samples 2006-08-29 17:47:17 +02:00
Mathieu Lacage 9c46cb37df remove files not needed 2006-08-29 17:45:05 +02:00
Mathieu Lacage a91bbbc401 ignore useless files 2006-08-29 17:43:19 +02:00
Mathieu Lacage 5c90e561b4 import from yans 2006-08-29 17:42:13 +02:00
Mathieu Lacage ae6d55badc add scons build 2006-08-29 17:34:37 +02:00
Unknown 41deba522f test of commit 2006-08-26 14:20:18 -07:00
250 changed files with 50936 additions and 615 deletions
+9
View File
@@ -0,0 +1,9 @@
.*.orig$
.*\.o$
.*~$
build-dir
build
.*\.sconsign
doc/html.*
doc/latex.*
.lock-wscript
+4
View File
@@ -0,0 +1,4 @@
56928998e05c9c11f5f3aefe79be8d2843e0db88 release ns-3.0.1
7ac5a4b0969b255c4824c926c2b37ef450136ce9 release ns-3.0.2
0dc81e76166c56aaae64da48b673b62155943aad packet-history-working
38099dd26e9467b8f49f8632f22789858149a6e7 release ns-3.0.3
+6 -1
View File
@@ -1 +1,6 @@
Bilbo The Hobbit
Raj Bhattarcharjea (raj.b@gatech.edu)
Gustavo Carneiro (gjc@inescporto.pt, gjcarneiro@gmail.com)
Craig Dowell (craigdo@ee.washington.edu)
Tom Henderson (tomhend@u.washington.edu)
Mathieu Lacage (mathieu.lacage@sophia.inria.fr)
George F. Riley (riley@ece.gatech.edu)
+339
View File
@@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
+170 -2
View File
@@ -1,3 +1,171 @@
empty README
random test
The Network Simulator, Version 3
--------------------------------
Table of Contents:
------------------
1) An Open Source project
2) An overview of the ns-3 project
3) Building ns-3
4) Running ns-3
5) Getting access to the ns-3 documentation
6) Working with the development version of ns-3
1) An Open Source project
-------------------------
ns-3 is an Open Source project. We intend to make this
project a successful collaborative project: we hope that
the missing pieces of the models we have not yet implemented
will be contributed by the community in an open collaboration
process.
Contributing to the ns-3 project is still a very informal
process because that process depends heavily on the background
of the people involved, the amount of time they can invest
and the type of model they want to work on.
Despite this lack of a formal process, there are a number of
steps which naturally stem from the open-source roots of the
project. These steps are described in doc/contributing.txt
2) An overview of the ns-3 project
----------------------------------
This package contains the latest version of ns-3 which aims
at being a replacement for ns-2. Currently, ns-3 provides a
number of very simple network simulation models:
- an ipv4 and udp stack
- arp support at the bottom of the stack
- point-to-point physical-layer links
- OnOff traffic generator
Our focus to date has been on getting an overall software
framework in place. The framework is there to make adding
new models as simple as possible:
- an extensive tracing system can be used to connect
any number of arbitrary trace sources to any number
of trace sinks. This tracing system is decoupled
from the act of serializing the trace events to a
file: users can and should provide their own
trace handling routines.
- simple file trace serialization support is included
to both text and pcap files.
- adding new MAC-level models simply requires subclassing
the pair of classes NetDevice and Channel.
- adding new traffic generation algorithms is also very
simple through the Application and the Socket classes.
3) Building ns-3
----------------
The code for the framework and the default models provided
by ns-3 is built as a set of libraries. User simulations
are expected to be written as simple programs that make
use of these ns-3 libraries.
To build the set of default libraries and the example
programs included in this package, you need to use the
tool 'scons'. Detailed information on how to install
and use scons is included in the file doc/build.txt
However, the real quick and dirty way to get started is to
type the command "scons" the the directory which contains
this README file. The files built will be copied in the
build-dir/dbg-shared/bin and build-dir/dbg-shared/lib
directories. build-dir/dbg-shared/bin will contain
one binary for each of the sample code in the 'samples'
directory and one binary for each of the detailed examples
found in the 'examples' directory.
The current codebase is expected to build and run on the
following set of platforms:
- linux x86 gcc 4.2, 4.1, and, 3.4.
- linux x86_64 gcc 4.0
- MacOS X ppc and x86
The current codebase is expected to fail to build on
the following platforms:
- gcc 3.3 and earlier
- optimized builds on linux x86 gcc 4.0
- cygwin
Other platforms may or may not work: we welcome
patches to improve the portability of the code to these
other platforms.
4) Running ns-3
---------------
On recent Linux systems, once you have built ns-3, it
should be easy to run the sample programs with the
following command:
./build-dir/dbg-shared/bin/simple-p2p
or:
cd build-dir/dbg-shared/bin
./simple-p2p
That program should generate a simple-p2p.tr text
trace file and a set of simple-p2p-xx-xx.pcap binary
pcap trace files, which can be read by tcpdump.
5) Getting access to the ns-3 documentation
-------------------------------------------
Once you have verified that your build of ns-3 works by running
the simple-p2p example as outlined in 4) above, it is
quite likely that you will want to get started on reading
some ns-3 documentation.
All of that documentation should always be available from
the ns-3 website: http:://www.nsnam.org/ but we
include some of it in this release for ease of use.
This documentation includes:
- an architecture document which describes a very
high-level view of ns-3: it tries to explain the
use-cases the ns-3 developers really focused on when
doing the initial design and then goes on to explain
the structure of the resulting framework.
See the file doc/architecture.pdf
- a wiki for user-contributed tips: http://www.nsnam.org/wiki/
- an API documentation generated using doxygen: this is
a reference manual, most likely not very well suited
as introductory text:
http://www.nsnam.org/doxygen/index.html
If you want to re-generate this documentation, you can
easily do so:
- doc/architecture.pdf is generated from the architecture.tex
file in http://code.nsnam.org/docs
- the doxygen documentation is generated from the doc/doxygen.conf
configuration file. The command "scons doc" will generate it
as doc/html/index.html if you have installed the doxygen tools
(see http://www.doxygen.org)
6) Working with the development version of ns-3
-----------------------------------------------
If you want to download and use the development version
of ns-3, you need to use the tool 'mercurial'. A quick and
dirty cheat sheet is included in doc/mercurial.txt but
reading through the mercurial tutorials included on the
mercurial website is usually a good idea if you are not
familiar with it.
If you have successfully installed mercurial, you can get
a copy of the development version with the following command:
"hg clone http://code.nsnam.org/ns-3-dev"
+44
View File
@@ -0,0 +1,44 @@
ns-3 RELEASE NOTES
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)
========================
- Enable Waf for release tarballs: users can now build ns-3
with the "waf" tool. See doc/build-waf.txt.
- Add support for variable time precision: it is now possible
to run a simulation with an accuracy which is higher or lower
than a nanosecond: seconds, milliseconds, microseconds,
femtoseconds and picoseconds are supported.
- Optimize and rework the COM framework, solidify the component
manager
- Many small API cleanups
Release 3.0.2 (2007/05/18)
========================
- Implement a new memory management infrastructure based
on reference counting and smart pointers (the latter being
optional)
- Implement a COM-like framework with support for QueryInterface
to provide object extensibility
- Add support for a BSD-style socket API for user applications
Release 3.0.1 (2007/03/31)
========================
- First public release; not yet pre-alpha.
- Simple UDP-based simulation script (examples/simple-p2p.cc)
+484
View File
@@ -0,0 +1,484 @@
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
import os.path
import build
version_file = open ('VERSION', 'r')
version = version_file.readline ()
version_file.close ()
version = version.strip ()
ns3 = build.Ns3()
ns3.build_dir = 'build-dir'
ns3.version = version
ns3.name = 'ns3'
ns3.distname = 'ns'
ns3.doxygen_config = os.path.join('doc', 'doxygen.conf')
ns3.add_extra_dist(os.path.join('doc', 'main.txt'))
ns3.add_extra_dist ('doc/architecture.pdf')
ns3.add_extra_dist ('doc/contributing.txt')
ns3.add_extra_dist ('doc/build.txt')
ns3.add_extra_dist ('doc/codingstd.txt')
ns3.add_extra_dist ('doc/mercurial.txt')
ns3.add_extra_dist ('README')
ns3.add_extra_dist ('RELEASE_NOTES')
ns3.add_extra_dist ('AUTHORS')
ns3.add_extra_dist ('VERSION')
ns3.add_extra_dist('ns3/_placeholder_')
for wscript in [
"src/core/wscript",
"src/node/wscript",
"src/devices/p2p/wscript",
"src/common/wscript",
"src/applications/wscript",
"src/simulator/wscript",
"src/internet-node/wscript",
"src/wscript",
"utils/wscript",
"samples/wscript",
"examples/wscript",
"wscript",
]:
ns3.add_extra_dist(wscript)
ns3.add_extra_dist('waf.bat')
#
# The Core module
#
core = build.Ns3Module('core', 'src/core')
ns3.add(core)
core.add_sources([
'callback-test.cc',
'debug.cc',
'assert.cc',
'ptr.cc',
'object.cc',
'test.cc',
'random-variable.cc',
'rng-stream.cc',
'uid-manager.cc',
'default-value.cc',
'command-line.cc',
'type-name.cc',
'component-manager.cc',
])
env = Environment()
if env['PLATFORM'] == 'posix' or env['PLATFORM'] == 'darwin' or env['PLATFORM'] == 'cygwin':
core.add_external_dep('pthread')
core.add_sources([
'unix-system-wall-clock-ms.cc',
])
elif env['PLATFORM'] == 'win32':
core.add_sources([
'win32-system-wall-clock-ms.cc',
])
core.add_headers ([
'uid-manager.h',
'singleton.h',
])
core.add_inst_headers([
'system-wall-clock-ms.h',
'empty.h',
'callback.h',
'ptr.h',
'object.h',
'debug.h',
'assert.h',
'fatal-error.h',
'test.h',
'random-variable.h',
'rng-stream.h',
'default-value.h',
'command-line.h',
'type-name.h',
'component-manager.h',
])
def config_core (env, config):
retval = []
# XXX This check is primitive but it should be
# good enough for now.
if config.CheckCHeader ('stdlib.h') == 1:
retval.append ('#define HAVE_STDLIB_H 1')
retval.append ('#define HAVE_GETENV 1')
else:
retval.append ('#undef HAVE_STDLIB_H')
retval.append ('#undef HAVE_GETENV')
return retval
core.add_config (config_core)
#
# The Simu module
#
simu = build.Ns3Module('simulator', 'src/simulator')
ns3.add(simu)
simu.add_dep('core')
simu.add_external_dep('m')
simu.add_sources([
'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',
])
simu.add_headers([
'scheduler-heap.h',
'scheduler-map.h',
'scheduler-list.h'
])
simu.add_inst_headers([
'high-precision.h',
'nstime.h',
'event-id.h',
'event-impl.h',
'simulator.h',
'scheduler.h',
'scheduler-factory.h',
'simulation-singleton.h',
])
high_precision_as_double = ARGUMENTS.get('high-precision-as-double', 'n')
if high_precision_as_double == 'y':
simu.add_inst_header ('high-precision-double.h')
simu.add_source ('high-precision-double.cc')
else:
simu.add_inst_headers ([
'high-precision-128.h',
'cairo-wideint-private.h'
])
simu.add_sources ([
'high-precision-128.cc',
'cairo-wideint.c',
])
def config_simulator (env, config):
retval = []
high_precision_as_double = ARGUMENTS.get('high-precision-as-double', 'n')
if high_precision_as_double == 'y':
retval.append ('#define USE_HIGH_PRECISION_DOUBLE 1')
else:
retval.append ('#undef USE_HIGH_PRECISION_DOUBLE')
if config.CheckCHeader ('stdint.h') == 1:
retval.append ('#define HAVE_STDINT_H 1')
elif config.CheckCHeader ('inttypes.h') == 1:
retval.append ('#define HAVE_INTTYPES_H 1')
elif config.CheckCHeader ('sys/inttypes.h') == 1:
retval.append ('#define HAVE_SYS_INT_TYPES_H 1')
return retval
simu.add_config (config_simulator)
#
# The Common module
#
common = build.Ns3Module('common', 'src/common')
common.add_deps(['core', 'simulator'])
ns3.add(common)
common.add_sources([
'buffer.cc',
'chunk.cc',
'header.cc',
'trailer.cc',
'packet-printer.cc',
'packet-metadata.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',
])
common.add_headers ([
])
common.add_inst_headers([
'buffer.h',
'chunk.h',
'header.h',
'trailer.h',
'tags.h',
'packet.h',
'packet-printer.h',
'packet-metadata.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',
'data-rate.h',
])
node = build.Ns3Module ('node', 'src/node')
ns3.add (node)
node.add_deps (['core', 'common', 'simulator'])
node.add_sources ([
'node.cc',
'ipv4-address.cc',
'net-device.cc',
'mac-address.cc',
'llc-snap-header.cc',
'ipv4-route.cc',
'queue.cc',
'drop-tail-queue.cc',
'channel.cc',
'node-list.cc',
'socket.cc',
'socket-factory.cc',
'udp.cc',
'ipv4.cc',
'application.cc',
])
node.add_inst_headers ([
'node.h',
'ipv4-address.h',
'net-device.h',
'mac-address.h',
'ipv4-route.h',
'queue.h',
'drop-tail-queue.h',
'llc-snap-header.h',
'channel.h',
'node-list.h',
'socket.h',
'socket-factory.h',
'udp.h',
'ipv4.h',
'application.h',
])
applications = build.Ns3Module ('applications', 'src/applications')
ns3.add (applications)
applications.add_deps (['node'])
applications.add_sources ([
'onoff-application.cc',
])
applications.add_inst_headers ([
'onoff-application.h',
])
inode = build.Ns3Module ('internet-node', 'src/internet-node')
ns3.add (inode)
inode.add_deps (['node'])
inode.add_sources ([
'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-l3-protocol.cc',
'ipv4-end-point.cc',
'udp-l4-protocol.cc',
'arp-header.cc',
'arp-cache.cc',
'arp-ipv4-interface.cc',
'arp-l3-protocol.cc',
'ipv4-loopback-interface.cc',
'header-utils.cc',
'udp-socket.cc',
'ipv4-end-point-demux.cc',
'arp-private.cc',
'ipv4-impl.cc',
'ipv4-private.cc',
'ascii-trace.cc',
'pcap-trace.cc',
'udp-impl.cc',
])
inode.add_headers ([
'ipv4-checksum.h',
'arp-header.h',
'arp-cache.h',
'arp-l3-protocol.h',
'ipv4-loopback-interface.h',
'l3-demux.h',
'header-utils.h',
'arp-ipv4-interface.h',
'udp-socket.h',
'udp-l4-protocol.h',
'arp-private.h',
'ipv4-impl.h',
'ipv4-private.h',
'ipv4-l3-protocol.h',
'l3-protocol.h',
'ipv4-l4-protocol.h',
'ipv4-l4-demux.h',
'ipv4-end-point-demux.h',
'ipv4-end-point.h',
'ipv4-header.h',
'udp-header.h',
'ipv4-interface.h',
'sgi-hashmap.h',
'udp-impl.h',
])
inode.add_inst_headers ([
'internet-node.h',
'ascii-trace.h',
'pcap-trace.h',
'ipv4-header.h',
'udp-header.h',
])
p2p = build.Ns3Module ('p2p', 'src/devices/p2p')
ns3.add (p2p)
p2p.add_deps (['node'])
p2p.add_sources ([
'p2p-net-device.cc',
'p2p-channel.cc',
'p2p-topology.cc',
])
p2p.add_inst_headers ([
'p2p-net-device.h',
'p2p-channel.h',
'p2p-topology.h',
])
# utils
run_tests = build.Ns3Module('run-tests', 'utils')
ns3.add(run_tests)
run_tests.set_executable()
run_tests.add_deps(['core', 'simulator', 'common'])
run_tests.add_source('run-tests.cc')
bench_object = build.Ns3Module('bench-object', 'utils')
ns3.add(bench_object)
bench_object.set_executable()
bench_object.add_deps(['core'])
bench_object.add_source('bench-object.cc')
bench_packets = build.Ns3Module('bench-packets', 'utils')
ns3.add(bench_packets)
bench_packets.set_executable()
bench_packets.add_deps (['core', 'common'])
bench_packets.add_source('bench-packets.cc')
bench_simu = build.Ns3Module('bench-simulator', 'utils')
ns3.add(bench_simu)
bench_simu.set_executable()
bench_simu.add_dep('simulator')
bench_simu.add_source('bench-simulator.cc')
replay_simu = build.Ns3Module('replay-simulation', 'utils')
ns3.add(replay_simu)
replay_simu.set_executable()
replay_simu.add_dep('simulator')
replay_simu.add_source('replay-simulation.cc')
# samples
sample_debug = build.Ns3Module('sample-debug', 'samples')
sample_debug.set_executable()
ns3.add(sample_debug)
sample_debug.add_dep('core')
sample_debug.add_source('main-debug.cc')
sample_debug.add_source('main-debug-other.cc')
sample_packet_printer = build.Ns3Module('sample-packet-printer', 'samples')
sample_packet_printer.set_executable()
ns3.add(sample_packet_printer)
sample_packet_printer.add_deps (['common', 'internet-node'])
sample_packet_printer.add_source('main-packet-printer.cc')
sample_callback = build.Ns3Module('sample-callback', 'samples')
sample_callback.set_executable()
ns3.add(sample_callback)
sample_callback.add_dep('core')
sample_callback.add_source('main-callback.cc')
sample_ptr = build.Ns3Module('sample-ptr', 'samples')
sample_ptr.set_executable()
ns3.add(sample_ptr)
sample_ptr.add_dep('core')
sample_ptr.add_source('main-ptr.cc')
sample_trace = build.Ns3Module('sample-trace', 'samples')
#ns3.add(sample_trace)
sample_trace.add_dep('common')
sample_trace.set_executable()
sample_trace.add_source('main-trace.cc')
sample_query_interface = build.Ns3Module('sample-query-interface', 'samples')
ns3.add(sample_query_interface)
sample_query_interface.add_dep('common')
sample_query_interface.set_executable()
sample_query_interface.add_source('main-query-interface.cc')
sample_simu = build.Ns3Module('sample-simulator', 'samples')
ns3.add(sample_simu)
sample_simu.set_executable()
sample_simu.add_dep('simulator')
sample_simu.add_source('main-simulator.cc')
sample_packet = build.Ns3Module('sample-packet', 'samples')
ns3.add(sample_packet)
sample_packet.set_executable()
sample_packet.add_dep('common')
sample_packet.add_source('main-packet.cc')
sample_test = build.Ns3Module('sample-test', 'samples')
sample_test.set_executable()
ns3.add(sample_test)
sample_test.add_dep('core')
sample_test.add_source('main-test.cc')
sample_simple = build.Ns3Module('sample-simple', 'samples')
sample_simple.set_executable()
ns3.add(sample_simple)
sample_simple.add_deps(['core', 'simulator', 'node', 'internet-node'])
sample_simple.add_source('main-simple.cc')
sample_sp2p = build.Ns3Module('sample-simple-p2p', 'samples')
sample_sp2p.set_executable()
#n3.add(sample_sp2p)
sample_sp2p.add_deps(['core', 'simulator', 'node', 'internet-node', 'p2p'])
sample_sp2p.add_source('main-simple-p2p.cc')
sample_default_value = build.Ns3Module('sample-default-value', 'samples')
sample_default_value.set_executable()
ns3.add(sample_default_value)
sample_default_value.add_deps(['core', 'simulator', 'node', 'p2p'])
sample_default_value.add_source('main-default-value.cc')
sample_object = build.Ns3Module('sample-object', 'samples')
sample_object.set_executable()
ns3.add(sample_object)
sample_object.add_deps(['core'])
sample_object.add_source('main-object.cc')
sample_component_manager = build.Ns3Module('sample-component-manager', 'samples')
sample_component_manager.set_executable()
ns3.add(sample_component_manager)
sample_component_manager.add_deps(['core'])
sample_component_manager.add_source('main-component-manager.cc')
# examples
example_simple_p2p = build.Ns3Module('simple-p2p', 'examples')
example_simple_p2p.set_executable()
ns3.add(example_simple_p2p)
example_simple_p2p.add_deps(['core', 'simulator', 'node', 'p2p', 'internet-node', 'applications'])
example_simple_p2p.add_source('simple-p2p.cc')
ns3.generate_dependencies()
+1
View File
@@ -0,0 +1 @@
3.0.4
+561
View File
@@ -0,0 +1,561 @@
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
# Copyright (c) 2006 INRIA
# 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
import os
import os.path
import shutil
from SCons.Environment import Environment
from SCons.Builder import Builder
from SCons.Action import Action
import SCons
# hack stolen from wengo
# to get an ARGUMENTS defined correctly
try:
ARGUMENTS = SCons.Script.ARGUMENTS
COMMAND_LINE_TARGETS = SCons.Script.COMMAND_LINE_TARGETS
except AttributeError:
from SCons.Script.SConscript import Arguments
from SCons.Script.SConscript import CommandLineTargets
ARGUMENTS = Arguments
COMMAND_LINE_TARGETS = CommandLineTargets
class Ns3Module:
def __init__(self, name, dir):
self.sources = []
self.inst_headers = []
self.headers = []
self.extra_dist = []
self.deps = []
self.external_deps = []
self.config = []
self.name = name
self.dir = dir
self.executable = False
self.library = True
self.ldflags = []
self.header_inst_dir = ''
def set_library(self):
self.library = True
self.executable = False
def set_executable(self):
self.library = False
self.executable = True
def add_config(self, config_fn):
self.config.append(config_fn)
def add_extra_dist(self, dist):
self.extra_dist.append(dist)
def add_external_dep(self, dep):
self.external_deps.append(dep)
def add_dep(self, dep):
self.deps.append(dep)
def add_deps(self, deps):
self.deps.extend(deps)
def add_source(self, source):
self.sources.append(source)
def add_sources(self, sources):
self.sources.extend(sources)
def add_header(self, header):
self.headers.append(header)
def add_headers(self, headers):
self.headers.extend(headers)
def add_inst_header(self, header):
self.inst_headers.append(header)
def add_inst_headers(self, headers):
self.inst_headers.extend(headers)
def add_ldflags (self, ldflags):
self.ldflags.extend (ldflags)
def add_ldflag (self, ldflag):
self.add_ldflags ([ldflag])
def set_header_inst_dir (self, inst_dir):
self.header_inst_dir = inst_dir
def MyCopyAction(target, source, env):
try:
if len(target) == len(source):
for i in range(len(target)):
shutil.copy(source[i].path, target[i].path)
return 0
else:
return 'invalid target/source match'
except:
print
return 'exception'
def MyCopyActionPrint(target, source, env):
if len(target) == len(source):
output = ''
for i in range(len(target)):
output = output + 'copy \'' + source[i].path + '\' to \'' + target[i].path + '\''
if i < len(target) - 1:
output = output + '\n'
return output
else:
return 'error in copy'
def GcxxEmitter(target, source, env):
if os.path.exists(source[0].path):
return [target, source]
else:
return [[], []]
def MyRmTree(target, source, env):
shutil.rmtree(env['RM_DIR'])
return 0
def MyRmTreePrint(target, source, env):
return ''
def print_cmd_line(s, target, src, env):
print 'Building ' + (' and '.join([str(x) for x in target])) + '...'
class Ns3BuildVariant:
def __init__(self):
self.static = False
self.gcxx_deps = False
self.gcxx_root = ''
self.build_root = ''
self.env = None
class Ns3:
def __init__(self):
self.__modules = []
self.extra_dist = []
self.build_dir = 'build'
self.version = '0.0.1'
self.name = 'noname'
self.distname = 'noname'
self.doxygen_config = ''
def add(self, module):
self.__modules.append(module)
def add_extra_dist(self, dist):
self.extra_dist.append(dist)
def __get_module(self, name):
for module in self.__modules:
if module.name == name:
return module
return None
def get_mod_output(self, module, variant):
if module.executable:
suffix = variant.env.subst(variant.env['PROGSUFFIX'])
filename = os.path.join(variant.build_root, 'bin',
module.name + suffix)
else:
if variant.static:
prefix = variant.env['LIBPREFIX']
suffix = variant.env['LIBSUFFIX']
else:
prefix = variant.env['SHLIBPREFIX']
suffix = variant.env['SHLIBSUFFIX']
prefix = variant.env.subst(prefix)
suffix = variant.env.subst(suffix)
filename = os.path.join(variant.build_root, 'lib',
prefix + module.name + suffix)
return filename
def get_obj_builders(self, variant, module):
env = variant.env.Copy ()
objects = []
hash = {}
self.get_internal_deps (module, hash)
for dep in hash.values ():
if dep.header_inst_dir != '':
inc_dir = os.path.join(variant.build_root, 'include',
self.name, dep.header_inst_dir)
env.Append (CPPPATH = [inc_dir])
if len(module.config) > 0:
src_config_file = os.path.join(self.build_dir, 'config', module.name + '-config.h')
tgt_config_file = os.path.join(variant.build_root, 'include',
self.name, module.name + '-config.h')
for source in module.sources:
obj_file = os.path.splitext(source)[0] + '.o'
tgt = os.path.join(variant.build_root, module.dir, obj_file)
src = os.path.join(module.dir, source)
if variant.static:
obj_builder = env.StaticObject(target = tgt, source = src)
else:
obj_builder = env.SharedObject(target = tgt, source = src)
if len(module.config) > 0:
config_file = env.MyCopyBuilder(target = [tgt_config_file],
source = [src_config_file])
env.Depends(obj_builder, config_file)
if variant.gcxx_deps:
gcno_tgt = os.path.join(variant.build_root, module.dir,
os.path.splitext(source)[0] + '.gcno')
gcda_tgt = os.path.join(variant.build_root, module.dir,
os.path.splitext(source)[0] + '.gcda')
gcda_src = os.path.join(variant.gcxx_root, module.dir,
os.path.splitext(source)[0] + '.gcda')
gcno_src = os.path.join(variant.gcxx_root, module.dir,
os.path.splitext(source)[0] + '.gcno')
gcno_builder = env.CopyGcxxBuilder(target = gcno_tgt, source = gcno_src)
gcda_builder = env.CopyGcxxBuilder(target = gcda_tgt, source = gcda_src)
env.Depends(obj_builder, gcda_builder)
env.Depends(obj_builder, gcno_builder)
objects.append(obj_builder)
return objects
def get_internal_deps(self, module, hash):
for dep_name in module.deps:
dep = self.__get_module(dep_name)
hash[dep_name] = dep
self.get_internal_deps(dep, hash)
def get_external_deps(self, module):
hash = {}
self.get_internal_deps(module, hash)
ext_hash = {}
for mod in hash.values():
for ext_dep in mod.external_deps:
ext_hash[ext_dep] = 1
return ext_hash.keys()
def get_sorted_deps(self, module):
h = {}
self.get_internal_deps(module, h)
modules = []
for dep in h.keys():
deps_copy = []
mod = h[dep]
deps_copy.extend(mod.deps)
modules.append([mod, deps_copy])
sorted = []
while len(modules) > 0:
to_remove = []
for item in modules:
if len(item[1]) == 0:
to_remove.append(item[0].name)
for item in to_remove:
for i in modules:
if item in i[1]:
i[1].remove(item)
new_modules = []
for mod in modules:
found = False
for i in to_remove:
if i == mod[0].name:
found = True
break
if not found:
new_modules.append(mod)
modules = new_modules
sorted.extend(to_remove)
sorted.reverse()
# append external deps
ext_deps = self.get_external_deps(module)
for dep in ext_deps:
sorted.append(dep)
return sorted
def gen_mod_dep(self, variant):
build_root = variant.build_root
cpp_path = os.path.join(variant.build_root, 'include')
env = variant.env
env.Append(CPPPATH = [cpp_path])
header_dir = os.path.join(build_root, 'include', self.name)
lib_path = os.path.join(build_root, 'lib')
env.Append (LIBPATH = [lib_path])
module_builders = []
for module in self.__modules:
my_env = env.Copy ();
objects = self.get_obj_builders(variant, module)
libs = self.get_sorted_deps(module)
my_env.Append (LIBS = libs)
my_env.Append (LINKFLAGS = module.ldflags)
filename = self.get_mod_output(module, variant)
if module.executable:
module_builder = my_env.Program(target=filename, source=objects)
else:
if variant.static:
module_builder = my_env.StaticLibrary(target=filename, source=objects)
else:
module_builder = my_env.SharedLibrary(target=filename, source=objects)
for dep_name in module.deps:
dep = self.__get_module(dep_name)
my_env.Depends(module_builder, self.get_mod_output(dep, variant))
for header in module.inst_headers:
if module.header_inst_dir != '':
tgt = os.path.join(header_dir, module.header_inst_dir, header)
else:
tgt = os.path.join(header_dir, header)
src = os.path.join(module.dir, header)
#builder = env.Install(target = tgt, source = src)
header_builder = my_env.MyCopyBuilder(target=tgt, source=src)
my_env.Depends(module_builder, header_builder)
module_builders.append(module_builder)
return module_builders
def gen_mod_config(self, env):
config_dir = os.path.join(self.build_dir, 'config')
for module in self.__modules:
if len(module.config) > 0:
config_file = os.path.join(config_dir, module.name + '-config.h')
config_file_guard = module.name + '_CONFIG_H'
config_file_guard.upper()
if not os.path.isfile(config_file):
if not os.path.isdir(config_dir):
os.makedirs(config_dir)
outfile = open(config_file, 'w')
outfile.write('#ifndef ' + config_file_guard + '\n')
outfile.write('#define ' + config_file_guard + '\n')
config = env.Configure()
for fn in module.config:
output = fn(env, config)
for o in output:
outfile.write(o)
outfile.write('\n')
outfile.write('#endif /*' + config_file_guard + '*/\n')
config.Finish()
def generate_dependencies(self):
inheritenv = (ARGUMENTS.get('inheritenv', 'n') in 'yY1')
if inheritenv:
env = Environment(ENV=os.environ)
else:
env = Environment()
self.gen_mod_config(env)
cc = env['CC']
cxx = env.subst(env['CXX'])
if cc == '':
print "Missing C compiler."
env.Exit (1);
if cxx == '':
print "Missing C++ compiler."
env.Exit (1);
common_flags = ARGUMENTS.get('cflags', '').split(' ')
cxxflags = ARGUMENTS.get('cxxflags', '').split(' ')
ldflags = ARGUMENTS.get('ldflags', '').split(' ')
if cc == 'cl' and cxx == 'cl':
env = Environment(tools=['mingw'])
cc = env['CC']
cxx = env.subst(env['CXX'])
if cc == 'gcc' and cxx == 'g++':
common_flags.extend(['-g3', '-Wall', '-Werror'])
debug_flags = []
opti_flags = ['-O3']
elif cc == 'cl' and cxx == 'cl':
env = Environment(ENV=os.environ)
debug_flags = ['-W1', '-GX', '-EHsc', '-D_DEBUG', '/MDd']
opti_flags = ['-O2', '-EHsc', '-DNDEBUG', '/MD']
cc = ARGUMENTS.get ('cc', '')
cxx = ARGUMENTS.get ('cxx', '')
if cc != '':
env.Replace (CC = cc)
if cxx != '':
env.Replace (CXX = cxx)
env.Append(CCFLAGS = common_flags,
CPPDEFINES = ['RUN_SELF_TESTS'],
TARFLAGS = '-c -z',
CPPFLAGS = cxxflags,
LINKFLAGS = ldflags)
if env['PLATFORM'] == 'posix':
env.Append(LINKFLAGS = ' -z origin')
env.Append(RPATH=env.Literal(os.path.join('\\$$ORIGIN', os.pardir, 'lib')))
verbose = ARGUMENTS.get('verbose', 'n')
if verbose == 'n':
env['PRINT_CMD_LINE_FUNC'] = print_cmd_line
header_builder = Builder(action = Action(MyCopyAction, strfunction=MyCopyActionPrint))
env.Append(BUILDERS = {'MyCopyBuilder':header_builder})
gcxx_builder = Builder(action = Action(MyCopyAction, strfunction=MyCopyActionPrint),
emitter = GcxxEmitter)
env.Append(BUILDERS = {'CopyGcxxBuilder':gcxx_builder})
variant = Ns3BuildVariant()
builders = []
gcov_env = env.Copy()
gcov_env.Append(CFLAGS = ['-fprofile-arcs', '-ftest-coverage'],
CXXFLAGS = ['-fprofile-arcs', '-ftest-coverage'],
LINKFLAGS = ['-fprofile-arcs'])
# code coverage analysis
variant.static = False
variant.env = gcov_env
variant.build_root = os.path.join(self.build_dir, 'gcov')
builders = self.gen_mod_dep(variant)
for builder in builders:
gcov_env.Alias('gcov', builder)
gcov_env.Alias('lcov-report')
if 'lcov-report' in COMMAND_LINE_TARGETS:
lcov_report_dir = os.path.join(self.build_dir, 'lcov-report')
create_dir_command = "rm -rf " + lcov_report_dir
create_dir_command += " && mkdir " + lcov_report_dir + ";"
gcov_env.Execute(create_dir_command)
info_file = os.path.join(lcov_report_dir, self.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.build_root,
'include')
gcov_env.Execute(lcov_command)
genhtml_command = "utils/lcov/genhtml -o " + lcov_report_dir
genhtml_command += " " + info_file
gcov_env.Execute(genhtml_command)
opt_env = env.Copy()
opt_env.Append(CFLAGS=opti_flags,
CXXFLAGS=opti_flags,
CPPDEFINES=['NDEBUG'])
# optimized static support
variant.static = True
variant.env = opt_env
variant.build_root = os.path.join(self.build_dir, 'opt-static')
builders = self.gen_mod_dep(variant)
for builder in builders:
opt_env.Alias('opt-static', builder)
opt_env = env.Copy()
opt_env.Append(CFLAGS = opti_flags,
CXXFLAGS = opti_flags,
CPPDEFINES = ['NDEBUG'])
# optimized shared support
variant.static = False
variant.env = opt_env
variant.build_root = os.path.join(self.build_dir, 'opt-shared')
builders = self.gen_mod_dep(variant)
for builder in builders:
opt_env.Alias('opt-shared', builder)
arc_env = env.Copy()
arc_env.Append(CFLAGS=opti_flags,
CXXFLAGS=opti_flags,
CPPDEFINES=['NDEBUG'])
arc_env.Append(CFLAGS=['-frandom-seed=0', '-fprofile-generate'],
CXXFLAGS=['-frandom-seed=0', '-fprofile-generate'],
LINKFLAGS=['-frandom-seed=0', '-fprofile-generate'])
# arc profiling
variant.static = False
variant.env = arc_env
variant.build_root = os.path.join(self.build_dir, 'opt-arc')
builders = self.gen_mod_dep(variant)
for builder in builders:
arc_env.Alias('opt-arc', builder)
arcrebuild_env = env.Copy()
arcrebuild_env.Append(CFLAGS=opti_flags,
CXXFLAGS=opti_flags,
CPPDEFINES=['NDEBUG'])
arcrebuild_env.Append(CFLAGS=['-frandom-seed=0', '-fprofile-use'],
CXXFLAGS=['-frandom-seed=0', '-fprofile-use'],
LINKFLAGS=['-frandom-seed=0', '-fprofile-use'])
# arc rebuild
variant.static = False
variant.env = arcrebuild_env
variant.gcxx_deps = True
variant.gcxx_root = os.path.join(self.build_dir, 'opt-arc')
variant.build_root = os.path.join(self.build_dir, 'opt-arc-rebuild')
builders = self.gen_mod_dep(variant)
for builder in builders:
arcrebuild_env.Alias('opt-arc-rebuild', builder)
variant.gcxx_deps = False
dbg_env = env.Copy()
dbg_env.Append(CFLAGS = debug_flags,
CXXFLAGS = debug_flags,
CPPDEFINES = ['NS3_DEBUG_ENABLE',
'NS3_ASSERT_ENABLE'])
# debug static support
variant.static = True
variant.env = dbg_env
variant.build_root = os.path.join(self.build_dir, 'dbg-static')
builders = self.gen_mod_dep(variant)
for builder in builders:
dbg_env.Alias('dbg-static', builder)
dbg_env = env.Copy()
dbg_env.Append(CFLAGS=debug_flags,
CXXFLAGS=debug_flags,
CPPDEFINES = ['NS3_DEBUG_ENABLE',
'NS3_ASSERT_ENABLE'])
# debug shared support
variant.static = False
variant.env = dbg_env
variant.build_root = os.path.join(self.build_dir, 'dbg-shared')
builders = self.gen_mod_dep(variant)
for builder in builders:
dbg_env.Alias('dbg-shared', builder)
env.Alias('dbg', 'dbg-shared')
env.Alias('opt', 'opt-shared')
env.Default('dbg')
env.Alias('all', ['dbg-shared', 'dbg-static', 'opt-shared', 'opt-static'])
# dist support
dist_env = env.Copy()
if dist_env['PLATFORM'] == 'posix' or dist_env['PLATFORM'] == 'darwin':
dist_list = []
for module in self.__modules:
for f in module.sources:
dist_list.append(os.path.join(module.dir, f))
for f in module.headers:
dist_list.append(os.path.join(module.dir, f))
for f in module.inst_headers:
dist_list.append(os.path.join(module.dir, f))
for f in module.extra_dist:
dist_list.append(os.path.join(module.dir, f))
for f in self.extra_dist:
dist_list.append(f)
dist_list.append (self.doxygen_config)
dist_list.append('SConstruct')
dist_list.append('build.py')
targets = []
basename = self.distname + '-' + self.version
for src in dist_list:
tgt = os.path.join(basename, src)
targets.append(dist_env.MyCopyBuilder(target=tgt, source=src))
tar = basename + '.tar.gz'
zip = basename + '.zip'
tmp_tar = os.path.join(self.build_dir, tar)
tmp_zip = os.path.join(self.build_dir, zip)
dist_tgt = [tar, zip]
dist_src = [tmp_tar, tmp_zip]
dist_env.Tar(tmp_tar, targets)
dist_env.Zip(tmp_zip, targets)
dist_builder = dist_env.MyCopyBuilder(target=dist_tgt, source=dist_src)
dist_env.Alias('dist', dist_builder)
dist_env.Append(RM_DIR=basename)
dist_env.AddPostAction(dist_builder, dist_env.Action(MyRmTree,
strfunction=MyRmTreePrint))
dist_builder = dist_env.MyCopyBuilder(target=dist_tgt, source=dist_src)
dist_env.Alias('fastdist', dist_tgt)
# distcheck
distcheck_list = []
for src in dist_list:
tgt = os.path.join(self.build_dir, basename, src)
distcheck_list.append(tgt)
untar = env.Command(distcheck_list, tar,
['cd ' + self.build_dir + ' && tar -zxf ../' + tar])
scons_dir = os.path.join(self.build_dir, basename)
distcheck_builder = env.Command('x', distcheck_list,
['cd ' + scons_dir + ' && scons'])
env.AlwaysBuild(distcheck_builder)
env.Alias('distcheck', distcheck_builder)
if self.doxygen_config != '':
doxy = env.Command('doc/html/*', self.doxygen_config,
['doxygen ' + self.doxygen_config])
env.AlwaysBuild(doxy)
env.Alias('doc', doxy)
+106
View File
@@ -0,0 +1,106 @@
The Waf build system is used to build ns-3. Waf is a Python-based
build system (http://www.freehackers.org/~tnagy/waf.html)
=== Installing Waf ===
If this file is part of a development release tarball, the top-level
ns-3 directory should contain a current waf script.
However, the ns-3 Mercurial 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).
=== Building with Waf ===
To build ns-3 with waf type the commands:
1. waf configure [options]
2. waf
To see valid configure options, type waf --help. The most important
option is -d <debug level>. 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/<debuglevel>/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',
]
-612
View File
@@ -1,612 +0,0 @@
\documentclass[11pt]{article}
\usepackage{times}
\setlength{\textwidth}{6.5in}
\setlength{\textheight}{9in}
\setlength{\oddsidemargin}{0.0in}
\setlength{\evensidemargin}{0.0in}
\setlength{\topmargin}{-0.5in}
\def\nst{{\em ns--3}}
\newcommand{\code}[1]{\texttt{#1}}
\begin{document}
\begin{center}
{\Large Coding Standard for ns--3}\\
August 22, 2005
\end{center}
\section{Introduction}
The purpose of the \nst\ project is to build software which will last
many years: making sure that the code is readable and stays so is
one of the most important items required to achieve this goal. This
document thus outlines guidelines we plan to enforce on each component
integrated in \nst to ensure uniformity of the codebase which is
a first step towards readable code.
\section{Recommendations}
The following recommendations are not strict rules and some of them
are conflicting but the point here is to outline the fact that we
value more common-sense than strict adherence to the coding style
defined in this document.
\subsection{naming}
Types, methods, functions and variable names should be self-descriptive.
Avoid using acronyms, expand them, do not hesitate to use long names,
Avoid shortcuts such as \code{sz} for \code{size}. Long names sometimes get in the
way of being able to read the code:
\begin{verbatim}
for (int loopCount = 0; loopCount < max; loopCount++)
{
// code
}
\end{verbatim}
loopCount should be renamed to something shorter such as
\code{i}, \code{j}, \code{k}, \code{l}, \code{m}, and \code{n}
which are widely used names which identify loop counters:
\begin{verbatim}
for (int i = 0; i < max; i++)
{
// code
}
\end{verbatim}
Similarly, \code{tmp} is a common way to denote temporary variables. On
the other hand, \code{foo} is not an appropriate name: it says nothing
about the purpose of the variable.
If you use predicates (that is, functions, variables or methods
which return a single boolean value), prefix the
name with \code{is} or \code{has}.
\subsection{Memory management}
As much as possible, try to pass around objects
by value and allocate them on the stack. If you need to allocate
objects on the heap with new, make sure that the corresponding
call to delete happens where the new took place. i.e., avoid
passing around pointer ownership.
Avoid the use of reference counting and, more generaly, strive to
keep the memory-management model simple.
\subsection{Templates}
For now, templates are defined only in the simulator
core and are used everywhere else. Try to keep it that way by
avoiding defining new templates in model-specific code.
\section{Standards}
\subsection{General}
\begin{enumerate}
\item There will be no {\em tab} characters in the code. Rather, repeated
spaces are used to separate the characters as needed.
\item No line of code will be longer than 80 characters in length, to
prevent lines wrapping in the {\tt emacs} or {\tt vi} editors. For both
of these linux text editing tools, the default is a window that is
exactly 80 characters wide, so if none of the lines wrap when editing
in {\tt emacs} or {\tt vi} this requirement is met.
\item Each C++ statement will be on a separate line. The only exception
is when an {\tt if}, {\tt else}, {\tt for} or {\tt while}
statement has a single
statement sub--block these can be on the same line.
Examples:
\begin{tt}
int i = 0; // Right\\
i = 10; j = 20; // Wrong. Two statements same line\\
Sub1(k); Sub2(k); // Wrong. Two statements same line\\
if (done) break; // Right. If statement with single statement sub-block
\end{tt}
\item Each variable declaration will be on a separate line.
Examples:
\begin{tt}
\begin{tabbing}
int c, d; \=// Wrong. c and d defined on same line.\\
int a = 0; \\
int b = 0; \>// Right. a and b on different lines\\
\end{tabbing}
\end{tt}
\item Variables should be declared at the point in the code
where they are needed, and should be assigned an initial value
at the time of declaration.
\begin{tt}
\begin{tabbing}
int a = 0; \=// Right, a is assigned in initial value.\\
int b; \> Wrong, b is not assigned an initial value.\\
int c = 0; \\
int d = Sub1(a, b);\\
c = Sub2(d); \> // Wrong, c should be declared here, not above
\end{tabbing}
\end{tt}
\item Excepting when used in a {\tt switch} statement, the open
and close curly braces (\{ and \}) are always on a separate line.
Examples:
\begin{tt}
\begin{tabbing}
aa\=aa\=aa\= \kill
for (int i = 0; i < MAX\_COUNT; ++i) \\
\>\{ // Right. Open brace on separate line \\
\>\>sum += i; \\
\>\>prod *= i; \\
\>\} // Right. Close brace on separate line
\end{tabbing}
\end{tt}
\begin{tt}
\begin{tabbing}
aa\=aa\=aa\= \kill
for (int i = 0; i < 10; ++i) \{ // Wrong. Open brace on same line\\
\>sum += i; \\
\>prod *= i; \} // Wrong. Close brace on same line
\end{tabbing}
\end{tt}
\item The C++ {\tt goto} statement is not to be used.
\end{enumerate}
\subsection{Commenting}
In general, comments should be use liberally throughout the program to
increase readability. Specifically:
\begin{enumerate}
\item C++ style comments using the {\tt //} delimeter
are to be used, rather than C style comments with the {\tt /*}
and {\tt */} delimieters.
\item Variable declaration should have a short, one or two line comment
describing the purpose of the variable, unless it is a
local variable whose use is obvious from the context. The short
comment should be on the same line as the variable declaration, unless it
is too long, in which case it should be on the preceding lines.
Example:
\begin{tt}
int averageGrade; // Computed average grade for this project \\
// Note. The above comment likely qualifies as \\
// obvious from context, and could be omitted.
\\
// Counts the total number of students completing the project, but\\
// does not include those not turning in the project. \\
int projectCount = 0;
\end{tt}
\item Every function should be preceded by a detailed comment block
describing what the function does, what the formal parameters are, and
what the return value is (if any).
\item Every class declaration should be preceded by a comment block
describing what the class is to be used for.
\item Unless obvious from context, each {\tt if} statement should
include a one--line comment on the open curly brace following describing
the {\tt TRUE} condition and the {\tt FALSE} condition.
Example:
\begin{tt}
\begin{tabbing}
aa\=aa\=aa\= \kill
if (iter == students.end()) \\
\>\{ // Student not found, add him \\
\>\>students.push\_back(thisStudent); \\
\>\} \\
else \\
\>\{ // Student exists, modify existing data \\
\>\>iter->grade += thisGrade; \\
\>\}
\end{tabbing}
\end{tt}
\item Class and function comments should adhere to the Doxygen standard
format, for automated extraction by the Doxygen tool. {\em Note from
GFR. We need a bit more here, as Doxygen has several possible methods
for commenting. I'll look them over and suggest an approach, for later
discussion}
\end{enumerate}
\subsection{Naming Conventions}
\begin{enumerate}
\item {\bf Variable Names}. All variables, including global variables,
local variables, formal parameters,
and member variables in classes will start with a
lower case letter, and consist of only alphabetic characters and numeric
digits. Capital letters are to be used when appropriate between words
in a variable name for increased readability.
Variable names should not contain the underscore character.
Examples:
{\tt int i;}\\
{\tt int nextIndexValue;}\\
{\tt int sum1;}\\
{\tt int loopCount10;}
\item {\bf Class Member and Global Variables}. To be able to distinguish
local variables from class member and global variables, prepend the
\code{m\_} prefix to class member variables and the \code{g\_} prefix
to global variables.
Examples:
\begin{verbatim}
class Foo {
private:
int m_myPrivateVar;
};
static int g_myGlobalVar;
\end{verbatim}
\item {\bf Subroutine Names}. All subroutine names, including global
routines and member functions in classes, will start with an upper case
letter, and consist of only alphabetic characters and numeric digits
(although digits should be rarely needed).
As in variable names, upper case letters are to be used between words as needed
to increase readability.
Examples:
{\tt int ComputeNextIterator()}\\
{\tt int Calculate()}\\
{\tt int TransmitPacket()}\\
{\tt int Dummy()}
\item {\bf Defined Constants}. All defined constants will be all upper
case letters or numeric digits, with the underscore character separating
words.
Examples:
{\tt typedef enum \{ PACKET\_RX, PACKET\_FIRST\_BIT\_RX, PACKET\_TX\} }\\
{\tt \#define NUMBER\_ELEMENTS 10}\\
{\tt const int LOOP\_COUNT = 100}
\item {\bf Defined Types}. All user defined types will end start with
an upper case letter, consist of upper and lower case letters only, and
end in {\tt \_t}.
Examples:
{\tt typedef double Time\_t; // Simulation time}\\
{\tt typedef unsigned long SimulatorUid\_t; // Unique ID for each event}\\
{\tt typedef unsigned long Event\_t; // Idenifies events in handler}\\
\item {\bf Class Names}. Class names will start with an upper case letter,
consist of only alphabetic characters, and include capital letters as
needed to increase readability.
Examples:
{\tt class DropTailQueue \{}\\
{\tt class Ferrari \{}\\
\end{enumerate}
%\newpage % Adjust as needed
\subsection{Statement Formatting}
\begin{enumerate}
\item {\bf Indention}. The basic indention level for all code
is four character positions. In some cases, indention to ``one--half''
level, is required as described below.
\item {\bf Continuation statements}. Frequently a single statement
is too long to fit within a single 80 column line. In this case, the
statement is simply continued on the next one or more lines. Each
continuation line must be indented at least one--half indention level,
and more as necessary to increase readability.
Examples:
\begin{tt}
\begin{tabbing}
longVariableName = \=(anotherLongName * shorterName) + (loopIndex2 * i) + \\
\>(k * j); // Correct, indented for neatness
\end{tabbing}
\end{tt}
\begin{tt}
\begin{tabbing}
a\=a\=a\= \kill
for (LongTypeName\_t longLoopIndexName = aLongExpression; \\
\>longLoopIndexName < MAX\_VALUE; \\
\>longLoopIndexName++) // Wrong, continuations not indented far enough
\end{tabbing}
\end{tt}
\begin{tt}
\begin{tabbing}
for (\=LongTypeName\_t longLoopIndexName = aLongExpression; \\
\>longLoopIndexName < MAX\_VALUE; \\
\>longLoopIndexName++) // Right, indented for readability
\end{tabbing}
\end{tt}
\item {\bf {\tt IF} Statements}.
The open curly brace following an {\tt IF} statement must be on the
following line, indented by one--half indention level.
The subsequent lines must
indented an additional one--half indention level.
{\tt IF} statements with only
one statement in either the {\tt TRUE} of {\tt FALSE} sub--blocks
may omit the curly braces. The {\tt ELSE} statement (if present)
must be on a line by itself.
Examples:
\begin{tt}
\begin{tabbing}
aa\=aa\=aa\= \kill
if (someCondition) \\
\>\{ // Describe TRUE condition here\\
\>\>i = k;\\
\>\>k = i + 2;\\
\>\} // Right, curly block indented one-half, statements one-half more
\end{tabbing}
\end{tt}
\begin{tt}
\begin{tabbing}
aa\=aa\=aa\= \kill
if (someCondition) \\
\>\{ // Describe TRUE condition here\\
\>\>i = k;\\
\>\>k = i + 2;\\
\>\} \\
else // Right, ELSE statement on separate line, same indent as IF \\
\>\{ // Describe FALSE condition here\\
\>\>i = k * 2; \\
\>\>k = i + 4; \\
\>\} // Right, closing curly brace lined up with open brace
\end{tabbing}
\end{tt}
\begin{tt}
\begin{tabbing}
aa\=aa\=aa\= \kill
if (someCondition) // Describe TRUE condition here\\
\>i = k; // Right, single line block need not have curly braces \\
\end{tabbing}
\end{tt}
\begin{tt}
if (someCondition) i = k; // Right, single statement may be on same line
\end{tt}
\item {\bf {\tt FOR} Statements}.
The open brace following a {\tt for} statement is indented
one-half level from the {\tt for} statement itself. Each statement
in the sub--block is indented one--half level from the curly brace.
If the sub--block is a single statement, the curly braces can be
omitted and the statement indented one level, or optionally appear
on the same line as the {\tt for} statement.
Example:
\begin{tt}
\begin{tabbing}
aa\=aa\=aa\= \kill
for (int i = 0; i < MAX\_COUNT; ++i) \\
\>\{ // Curly brace indented one-half level \\
\>\>sum += i; // Statements indented another one-half level \\
\>\>prod *= i; \\
\>\} // Close brace on same column as open brace \\
\end{tabbing}
\end{tt}
\begin{tt}
for (int i = 0; i < MAX\_COUNT; ++i) Sub1(i); // Right, single statement\\
\end{tt}
\item {\bf {\tt WHILE} Statements}.
{\tt While} statements are formatted similarly to {\tt IF} statements,
with curly braces indented one-half level on separate lines, and the
inner statements indented another half-level. If the sub--block has only
a single line, the curly braces can be omitted, and the statement may
appear on the same line as the {\tt WHILE} statement.
Examples:
\begin{tt}
\begin{tabbing}
aa\=aa\=aa\= \kill
while (someCondition) \\
\>\{ // Right, open brace indented one-half level \\
\>\>i = k; // Right, statements indented one-half level from open brace \\
\>\>k = i + 2;\\
\>\} // Right, close brace lines up with open brace
\end{tabbing}
\end{tt}
\begin{tt}
while (someCondition) i = i + 2; // Right, single stmt on same line
\end{tt}
\item {\bf Infinite Loops}.
Any loop intended to be infinite (of course with a {\tt break} statement
somewhere) should be of the form:
\begin{tt}
while(true) \\
{ // Loop until sentinel found\\
...code here \\
}
\end{tt}
\item {\bf {\tt SWITCH} Statements}.
The open curly brace for a {\tt switch} statement will be on the same
line as the {\tt switch} statement itself. Each {\tt case} statement
following is indented two columns from the switch statement. Each
statement in the {\tt case} block is indented two column from the
{\tt case} statement. The closing curly brace is on a separate line
by itself, indented two columns from the {\tt switch} statement.
Example:
\begin{tt}
\begin{tabbing}
aa\=aa\=aa\= \kill
switch(someCondition) \{ Right, open brace on same line as switch\\
\>case 0 : // Right, case indented two columns from switch\\
\>\>i = k; // Right, statements indented two columns from case \\
\>\>k = i + 2;\\
\>\>break;\\
\>case 1 : // Right, case indented two columns from switch\\
\>\>i = k + 2; // Right, statements indented two columns from case \\
\>\>k = i + 4;\\
\>\>break;\\
\>\} // Right, close brace lines up with case statements
\end{tabbing}
\end{tt}
\item {\bf Functions}. Since C and C++ do not allow nested functions,
all functions start with no indentation at column 0. The open curly
brace is on a line by itself immediately following the function header
and formal parameters, also in column 0. Any local variable declarations
immediately following the open curly brace also start at column 0.
One blank line follows the initial local variable declarations (if any).
The statements in the function body are indented one-half level
from the curly brace. Any variable declarations after the start of the
statements are indented at the same level as the preceding statement.
The closing brace is at column 0.
Example:
\begin{tt}
\begin{tabbing}
aa\=aa\=aa\=aa\= \kill
void Function1(int arg1, double arg2)\\
\{ // Right, curly brace at column 0\\
int local1 = 0; // Right, local variable at column 0\\
int local2;\\
\>\\
\>local2 = local1 + arg1 + arg2; // Right, indented two columns\\
\>int local3; // Right, variable at same level\\
\>local3 = Function2(local2);\\
\>if (someCondition)\\
\>\>\{\\
\>\>\>local3 = 0;\\
\>\>\>local2 = local1;\\
\>\>\>int local4 = local1 + 1; // Right, variable at same level\\
\>\>\>Function3(local4);\\
\>\>\}\\
\} // Right, close brace at column 0
\end{tabbing}
\end{tt}
\item {\bf Expressions}. Spaces should be used liberally in expressions
to increase readability. One space before and after each operator,
excepting the increment and decrement operators, leads to easy--to--read
expressions. Continued expressions should be indented as far as needed
for neatness and readability.
Examples:
\begin{tt}
i = k * 2 + 3 / var1++; // Right, spacing separating terms \\
\end{tt}
\begin{tt}
i = k*2+2/var1++; // Wrong, crowded together and hard to read
\end{tt}
\begin{tt}
\begin{tabbing}
someLongVariableName = \=anotherLongVariableName * shorterName + \\
\>anotherName; // Right, indented to line up
\end{tabbing}
\end{tt}
\end{enumerate}
\subsection{Header Files}
\begin{enumerate}
\item All header files will have a file name ending with {\tt .h}.
\item All header files should have a one line comment describing
the purpose of the header, and comments identifying the
author and the (approximate) date the file was created.
Example:
\begin{tt}
// ns3 Network Simulator - TCP Base Class Declaration \\
// George F. Riley. riley@ece.gatech.edu. \\
// Georgia Tech, Fall 2006
\end{tt}
\item All header files should have an ``include guard'' to prevent accidental
inclusion of the file multiple times in a single compilation unit. The include
guard should be named after the file name. If the file name is \code{foo-bar.h}, then the
include guard should be named \code{FOO\_BAR\_H}
Example:
\begin{tt}
\#ifndef FOO\_BAR\_H \\
\#define FOO\_BAR\_H \\
// (Contents of foo-bar.h here
\#endif
\end{tt}
\item Header files should avoid including other files whenever possible.
This can often be avoided with judicious use of the
{\tt class ClassName;} forward declaration.
Example:
\begin{tt}
// excerpt from application.h \\
class L4Protocol; \\
class Application \{ \\
.... \\
AddL4Proto(const L4Protocol\&); \\
.... \\
L4Protocol* l4Proto; \\
\};
\end{tt}
In the above example, the use of the forward declaration for {\tt L4Protocol}
obviates the need to include {\tt l4proto.h} in the application header
file.
\end{enumerate}
\subsection{Source Code Files}
\begin{enumerate}
\item All souce code files will have a file name ending with {\tt .cc}.
\item All source code files should have a one line comment describing
the purpose of the code, and comments identifying the
author and the (approximate) date the file was created.
Example:
\begin{tt}
// ns3 Network Simulator - TCP Base Class Implementation \\
// George F. Riley. riley@ece.gatech.edu. \\
// Georgia Tech, Fall 2006
\end{tt}
\item All {\tt \#include} directives should be grouped with {\em system}
files listed first (eg. {\tt \#include <iostream>}), followed by
\nst\ defined files (eg. {\tt \#include "tcp.h"}). Within a group,
the includes should be sorted in alphabetical order.
Example:
\begin{tt}
\#include <iostream> \\
\#include <list> \\
\#include <vector> \\
\#include "application.h" \\
\#include "dumbbell.h" \\
\#include "simulator.h" \\
\#include "tcp.h.h"
\end{tt}
\end{enumerate}
\end{document}
+210
View File
@@ -0,0 +1,210 @@
The Ns-3 Coding Style
/*
* Note: This file is incomplete and will be converted to non-text (html,pdf)
* formats at a future date
*/
1) Code layout
-----------
The code layout follows the GNU coding standard layout for C and extends
it to C++. Do not use tabs for indentation. Indentation spacing is 2
spaces as outlined below:
void
Foo (void)
{
if (test)
{
// do stuff here
}
else
{
// do other stuff here
}
for (int i = 0; i < 100; i++)
{
// do loop
}
while (test)
{
// do while
}
do
{
// do stuff
} while ();
}
The following is not recommended:
if (test) statement
if (test)
statement
for (...) statement
Each statement should be put on a separate line to increase readability.
Short one-line comments can use the C++ comment style, that is, '//'
but longer comments should use C-style comments:
/*
*
*
*/
2) Naming Patterns
---------------
2.1) Name encoding
-------------
Function, Method, and Type names should follow the CamelCase convention:
words are joined without spaces and are capitalized. For example,
"my computer" is transformed into MyComputer. Do not use all capital
letters such as MAC or, PHY, but choose instead Mac or Phy. Do not use
all capital letters, even for acronyms such as EDCA: use Edca instead.
The goal of the CamelCase convention is to ensure that the words which
make up a name can be separated by the eye: the initial Caps fills
that role.
Variable names should follow a slight variation on the base CamelCase
convention: camelBack. For example, the variable "user name" would be
named "userName". This variation on the basic naming pattern is used to
allow a reader to distinguish a variable name from its type. For example,
"UserName userName;" would be used to declare a variable named userName
of type UserName.
Global variables should be prefixed with a "g_" and member variables
(including static member variables) should be prefixed with a "m_". The
goal of that prefix is to give a reader a sense of where a variable of
a given name is declared to allow the reader to locate the variable
declaration and infer the variable type from that declaration. For example
you could declare in your class header my-class.h:
class MyClass
{
void MyMethod (int aVar);
int m_aVar;
static int m_anotherVar;
};
and implement in your class file my-class.cc:
int MyClass::m_anotherVar = 10;
static int g_aStaticVar = 100;
int g_aGlobalVar = 1000;
void
MyClass::MyMethod (int aVar)
{
m_aVar = aVar;
}
2.2) Choosing names
Variable, function, method, and type names should be based on the
english language. Furthermore, always try to choose descriptive
names for them. Types are often english names such as: Packet,
Buffer, Mac, or Phy. Functions and Methods are often named
based on verbs and adjectives: GetX, DoDispose, ClearArray, etc.
A long descriptive name which requires a lot of typing is always
better than a short name which is hard to decipher. Do not use
abbreviations in names unless the abbreviation is really unambiguous
and obvious to everyone. Do not use short inapropriate names such
as foo, bar, or baz. The name of an item should always match its
purpose. As such, names such as tmp to identify a temporary
variable or such as 'i' to identify a loop index are ok.
3) File layout and code organization
---------------------------------
A class named MyClass should be declared in a header named my-class.h
and implemented in a source file named my-class.cc. The goal of this
naming pattern is to allow a reader to quickly navigate through
the ns-3 codebase to locate the source file relevant to a specific
type.
Each my-class.h header should start with the following comments: the
first line ensures that developers who use the emacs editor will be
able to indent your code correctly. The following lines ensure that
your code is licensed under the GPL, that the copyright holders
are properly identified (typically, you or your employer), and
that the actual author of the code is identified. The latter is
purely informational and we use it to try to track the most
appropriate person to review a patch or fix a bug.
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) YEAR COPYRIGHTHOLDER
*
* 3-paragran GPL blurb
*
* Author: MyName <myemail@foo.com>
*/
Below these C-style comments, always include the following which
defines a set of header guards (MY_CLASS_H) used to avoid multiple
header includes, which ensures that your code is included
in the "ns3" namespace and which provides a set of doxygen comments
for the public part of your class API. Detailed information
on the set of tags available for doxygen documentation is described
in the doxygen website: http://www.doxygen.org.
#ifndef MY_CLASS_H
#define MY_CLASS_H
namespace n3 {
/**
* \brief short one-line description of the purpose of your class
*
* A longer description of the purpose of your class after a blank
* empty line.
*/
class MyClass
{
public:
MyClass ();
/**
* \param firstParam a short description of the purpose of this parameter
* \returns a short description of what is returned from this function.
*
* A detailed description of the purpose of the method.
*/
int DoFoo (int firstParam);
private:
void MyPrivateMethod (void);
int m_myPrivateMemberVariable;
};
} // namespace ns3
#endif /* MY_CLASS_H */
The my-class.cc file is structured similarly:
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) YEAR COPYRIGHTHOLDER
*
* 3-paragran GPL blurb
*
* Author: MyName <myemail@foo.com>
*/
#include "my-class.h"
namespace ns3 {
MyClass::MyClass ()
{}
...
} // namespace ns3
+63
View File
@@ -0,0 +1,63 @@
Contributing to the ns-3 project
--------------------------------
ns-3 is an open source project backed by an NSF CISE CRI grant.
Although the NSF PIs have specific aims to fulfill, we want others to
contribute, and we'd like to have a broad community of users and
developers, with the goal of a self-sustaining project downstream.
The project is currently in a bootstrapping phase, but we welcome
ambitious developers who might want to help shape the early design.
Despite the lack of a formal contribution process to the ns-3
project, there are a number of steps which we expect every
potential contributor to follow. These naturally stem from
the open-source roots of the project:
- first, you should subscribe to the ns-developers
mailing-list (see http://www.nsnam.org/mailing_lists.html)
- then, you should send an email there stating your interest
in working on a specific part of the models and trying
to explain how you would like to implement it, what
resources you have, etc.
- you should be prepared to work together with the other
potential contributors who want to work on the same models.
- you should be prepared to go through code reviews with the
ns-3 development team prior to integration. The goal of these
code reviews is to:
- ensure adherence to the coding style of the project
(see doc/codingstyle.html)
- ensure that the structure of your code has a certain
coherence with regard to the rest of the ns-3 codebase
- improve the quality of the code: we strongly believe in
the old saying: "many eyes make all bugs shallow".
- increase code reuse by trying to generalize certain
useful pieces of your code to make them available to
other models.
- you should be prepared to try to integrate as many tests
in the codebase as possible: we understand that writing
tests is not sexy and that not everyone is convinced that
they improve the code-writing poductivity which is why
we do not enforce strict rules about testing. However,
we expect model authors to answer basic questions about
how they plan to test and validate their models.
- you should be prepared to maintain your model once it is
integrated: while we consider every bug filed against the
simulator as being a bug we must deal with and while we
will try to fix as many bugs as humanly possible, we
also expect model authors to act as responsible maintainers
and be reactive to bug reports concerning their models.
- The project has decided upon GNU GPLv2 as the licensing structure.
All simulation software in the ns-3 repositories will be GNU GPLv2
or GNU GPLv2-compatible (with non-GPLv2 licensing reserved for
ports of pre-existing code under a different license, such as BSD).
You do not have to assign your copyright to the ns-3 project but
you must accept the terms of the GPLv2 and attest that your
contributions can be licensed under those terms. See the
following link:
http://www.fsf.org/licensing/licenses/info/GPLv2.html
+1231
View File
File diff suppressed because it is too large Load Diff
+68
View File
@@ -0,0 +1,68 @@
/**
* \mainpage An Introduction to ns-3
*
* The ns-3 library is split across multiple modules:
* - core: located in src/core and contains a number of facilities which
* do not depend on any other module. Some of these facilities are
* OS-dependent.
* - simulator: located in src/simulator and contains event scheduling
* facilities.
* - common: located in src/common and contains facilities specific
* to network simulations but shared by pretty much every model
* of a network component.
* - node: located in src/node. Defines the abstract interfaces which
* must be implemented by every node and more specifically, by ipv4 nodes.
* - devices: located in src/devices. Contains a set of MAC-level models
*
* The "core" module contains:
* - a Functor class: ns3::Callback
* - an os-independent interface to get access to the elapsed wall clock time: ns3::SystemWallClockMs
* - 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 base class for objects which need to support reference counting
* and QueryInterface: ns3::Object and ns3::InterfaceId
* - a ns3::ComponentManager which can be used to manage the creation
* of any object which derives from ns3::Object through an ns3::ClassId
* - a smart-pointer class ns3::Ptr designed to work together with ns3::Object
*
* The "simulator" module contains:
* - a time management class to hold a time and convert between various time units: ns3::Time
* - a scheduler base class used to implement new simulation event schedulers:
* ns3::Scheduler and ns3::SchedulerFactory
* - a simulator class used to create, schedule and cancel events: ns3::Simulator
*
* The "common" module contains:
* - a packet class to create and manipulate simulation packets: ns3::Packet, ns3::Header,
* and ns3::Trailer. This packet class also supports per-packet ns3::Tag which are
* globs of data which can be attached to any packet.
* - a set of low-level trace facilities: \ref lowleveltracing
*
* The "node" module contains:
* - a ns3::Node base class which should be subclassed by any new type of
* network Node.
* - models which abstract the MAC-layer from the IP layer protocols:
* ns3::NetDevice and ns3::Channel.
* - models which abstract the application-layer API: ns3::Application,
* ns3::Socket, ns3::SocketFactory, and, ns3::Udp
*
* The "internet-node" module contains a set of classes which implement the
* APIs defined in the "node" module:
* - an Ipv4/Udp stack with socket support
* - an ARP module
* - an InternetNode class which is a Node subclass.
*
* The "devices" module contains:
* - a PointToPoint MAC device: ns3::PointToPointNetDevice, ns3::PointToPointChannel,
* and ns3::PointToPointTopology.
*/
/**
* \namespace ns3
* \brief Every class exported by the ns3 library is enclosed in the
* ns3 namespace.
*/
/**
* \defgroup constants Constants
* \brief Constants you can change
*/
+45
View File
@@ -0,0 +1,45 @@
Introduction
------------
ns-3 uses the Mercurial software revision control system which
is a replacement for tools liks cvs or subversion. Thus, to get
access to the development versions of ns-3, you need to install
mercurial first. See http://www.selenic.com/mercurial/wiki/
Mercurial cheat sheet
---------------------
Look at our project history and source code:
-------------------------------------------
http://code.nsnam.org/ns-3-dev
clone this repository:
---------------------
hg clone http://code.nsnam.org/ns-3-dev
commit locally:
--------------
hg status
hg add <new files, if any>
hg ci -m "message"
pull development tree changes to your local repository:
------------------------------------------------------
hg ci -m "my local changes are recorded"
hg pull http://code.nsnam.org/ns-3-dev
hg update (apply the changes) OR
hg merge (if you've made local changes)
view the change log:
-------------------
hg log <file>
push upwards (developers access only):
--------------------------------------
To the main repository:
hg push ssh://code@code.nsnam.org/repos/ns-3-dev
To your private repository:
hg push ssh://username@code.nsnam.org//home/username/repositories/username/repository
+19
View File
@@ -0,0 +1,19 @@
Steps in doing an ns-3 release
1. prepare the source files
- revise and check in AUTHORS, if needed
- 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
- 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
+191
View File
@@ -0,0 +1,191 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* ns-2 simple.tcl script (ported from ns-2)
* Originally authored by Steve McCanne, 12/19/1996
*/
// Port of ns-2/tcl/ex/simple.tcl to ns-3
//
// Network topology
//
// n0
// \ 5 Mb/s, 2ms
// \ 1.5Mb/s, 10ms
// n2 -------------------------n3
// /
// / 5 Mb/s, 2ms
// n1
//
// - all links are p2p links with indicated one-way BW/delay
// - CBR/UDP flows from n0 to n3, and from n3 to n1
// - FTP/TCP flow from n0 to n3, starting at time 1.2 to time 1.35 sec.
// - UDP packet size of 210 bytes, with per-packet interval 0.00375 sec.
// (i.e., DataRate of 448,000 bps)
// - DropTail queues
// - Tracing of queues and packet receptions to file "simple-p2p.tr"
#include <iostream>
#include <fstream>
#include <string>
#include <cassert>
#include "ns3/command-line.h"
#include "ns3/default-value.h"
#include "ns3/ptr.h"
#include "ns3/random-variable.h"
#include "ns3/simulator.h"
#include "ns3/nstime.h"
#include "ns3/data-rate.h"
#include "ns3/ascii-trace.h"
#include "ns3/pcap-trace.h"
#include "ns3/internet-node.h"
#include "ns3/p2p-channel.h"
#include "ns3/p2p-net-device.h"
#include "ns3/mac-address.h"
#include "ns3/ipv4-address.h"
#include "ns3/ipv4.h"
#include "ns3/socket.h"
#include "ns3/ipv4-route.h"
#include "ns3/p2p-topology.h"
#include "ns3/onoff-application.h"
using namespace ns3;
int main (int argc, char *argv[])
{
// Users may find it convenient to turn on explicit debugging
// for selected modules; the below lines suggest how to do this
#if 0
DebugComponentEnable("Object");
DebugComponentEnable("Queue");
DebugComponentEnable("DropTailQueue");
DebugComponentEnable("Channel");
DebugComponentEnable("PointToPointChannel");
DebugComponentEnable("PointToPointNetDevice");
#endif
// Set up some default values for the simulation. Use the Bind()
// technique to tell the system what subclass of Queue to use,
// and what the queue limit is
// The below Bind command tells the queue factory which class to
// instantiate, when the queue factory is invoked in the topology code
Bind ("Queue", "DropTailQueue");
Bind ("OnOffApplicationPacketSize", "210");
Bind ("OnOffApplicationDataRate", "448kb/s");
//Bind ("DropTailQueue::m_maxPackets", 30);
// Allow the user to override any of the defaults and the above
// Bind()s at run-time, via command-line arguments
CommandLine::Parse (argc, argv);
// Here, we will explicitly create four nodes. In more sophisticated
// topologies, we could configure a node factory.
Ptr<Node> n0 = Create<InternetNode> ();
Ptr<Node> n1 = Create<InternetNode> ();
Ptr<Node> n2 = Create<InternetNode> ();
Ptr<Node> n3 = Create<InternetNode> ();
// We create the channels first without any IP addressing information
Ptr<PointToPointChannel> channel0 =
PointToPointTopology::AddPointToPointLink (
n0, n2, DataRate(5000000), MilliSeconds(2));
Ptr<PointToPointChannel> channel1 =
PointToPointTopology::AddPointToPointLink (
n1, n2, DataRate(5000000), MilliSeconds(2));
Ptr<PointToPointChannel> channel2 =
PointToPointTopology::AddPointToPointLink (
n2, n3, DataRate(1500000), MilliSeconds(10));
// Later, we add IP addresses.
PointToPointTopology::AddIpv4Addresses (
channel0, n0, Ipv4Address("10.1.1.1"),
n2, Ipv4Address("10.1.1.2"));
PointToPointTopology::AddIpv4Addresses (
channel1, n1, Ipv4Address("10.1.2.1"),
n2, Ipv4Address("10.1.2.2"));
PointToPointTopology::AddIpv4Addresses (
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<OnOffApplication> ooff = Create<OnOffApplication> (
n0,
Ipv4Address("10.1.3.2"),
80,
"Udp",
ConstantVariable(1),
ConstantVariable(0));
// Start the application
ooff->Start(Seconds(1.0));
ooff->Stop (Seconds(10.0));
// Create a similar flow from n3 to n1, starting at time 1.1 seconds
ooff = Create<OnOffApplication> (
n3,
Ipv4Address("10.1.2.1"),
80,
"Udp",
ConstantVariable(1),
ConstantVariable(0));
// Start the application
ooff->Start(Seconds(1.1));
ooff->Stop (Seconds(10.0));
// Here, finish off packet routing configuration
// This will likely set by some global StaticRouting object in the future
Ptr<Ipv4> ipv4;
ipv4 = n0->QueryInterface<Ipv4> (Ipv4::iid);
ipv4->SetDefaultRoute (Ipv4Address ("10.1.1.2"), 1);
ipv4 = n3->QueryInterface<Ipv4> (Ipv4::iid);
ipv4->SetDefaultRoute (Ipv4Address ("10.1.3.1"), 1);
// Configure tracing of all enqueue, dequeue, and NetDevice receive events
// Trace output will be sent to the simple-p2p.tr file
AsciiTrace asciitrace ("simple-p2p.tr");
asciitrace.TraceAllQueues ();
asciitrace.TraceAllNetDeviceRx ();
// Also configure some tcpdump traces; each interface will be traced
// The output files will be named simple-p2p.pcap-<nodeId>-<interfaceId>
// and can be read by the "tcpdump -r" command (use "-tt" option to
// display timestamps correctly)
PcapTrace pcaptrace ("simple-p2p.pcap");
pcaptrace.TraceAllIp ();
Simulator::Run ();
Simulator::Destroy ();
}
+13
View File
@@ -0,0 +1,13 @@
## -*- 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 = ["ns3-%s" % dep for dep in deps]
obj.source = source
return obj
obj = create_ns_prog('simple-p2p', 'simple-p2p.cc', deps=['p2p', 'internet-node'])
+1
View File
@@ -0,0 +1 @@
This is a placeholder file used only to keep the ns3 directory present (needed for the WAF build system).
+58
View File
@@ -0,0 +1,58 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
#include "ns3/callback.h"
#include "ns3/assert.h"
#include <iostream>
using namespace ns3;
static double
CbOne (double a, double b)
{
std::cout << "invoke cbOne a=" << a << ", b=" << b << std::endl;
return a;
}
class MyCb {
public:
int CbTwo (double a) {
std::cout << "invoke cbTwo a=" << a << std::endl;
return -5;
}
};
int main (int argc, char *argv[])
{
// return type: double
// first arg type: double
// second arg type: double
Callback<double, double, double> one;
// build callback instance which points to cbOne function
one = MakeCallback (&CbOne);
// this is not a null callback
NS_ASSERT (!one.IsNull ());
// invoke cbOne function through callback instance
double retOne;
retOne = one (10.0, 20.0);
// return type: int
// first arg type: double
Callback<int, double> two;
MyCb cb;
// build callback instance which points to MyCb::cbTwo
two = MakeCallback (&MyCb::CbTwo, &cb);
// this is not a null callback
NS_ASSERT (!two.IsNull ());
// invoke MyCb::cbTwo through callback instance
int retTwo;
retTwo = two (10.0);
two = MakeNullCallback<int, double> ();
// invoking a null callback is just like
// invoking a null function pointer:
// it will crash.
//int retTwoNull = two (20.0);
NS_ASSERT (two.IsNull ());
return 0;
}
+219
View File
@@ -0,0 +1,219 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 University of Washington
* 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
*/
#include <string>
#include "ns3/debug.h"
#include "ns3/assert.h"
#include "ns3/packet.h"
#include "ns3/drop-tail.h"
#include "ns3/layer-connector.h"
#include "ns3/channel.h"
using namespace ns3;
// ===========================================================================
// Cook up a simplistic Internet Node
// ===========================================================================
class FakeInternetNode : public LayerConnectorUpper
{
public:
FakeInternetNode ();
~FakeInternetNode ();
void Doit (void);
protected:
bool UpperDoSendUp (Packet &p);
bool UpperDoPull (Packet &p);
DropTailQueue m_dtqOutbound;
DropTailQueue m_dtqInbound;
};
FakeInternetNode::FakeInternetNode ()
{
NS_DEBUG_UNCOND("FakeInternetNode::FakeInternetNode ()");
}
FakeInternetNode::~FakeInternetNode ()
{
NS_DEBUG_UNCOND("FakeInternetNode::~FakeInternetNode ()");
}
void
FakeInternetNode::Doit (void)
{
NS_DEBUG_UNCOND("FakeInternetNode::Doit ()");
NS_DEBUG_UNCOND("FakeInternetNode::Doit (): **** Send outbound packet");
Packet p;
m_dtqOutbound.Enqueue(p);
UpperNotify();
}
bool
FakeInternetNode::UpperDoSendUp (Packet &p)
{
NS_DEBUG_UNCOND("FakeInternetNode::UpperDoSendUp (" << &p << ")");
NS_DEBUG_UNCOND("FakeInternetNode::UpperDoSendUp (): **** Receive inbound packet");
m_dtqInbound.Enqueue(p);
return m_dtqInbound.Dequeue(p);
}
bool
FakeInternetNode::UpperDoPull (Packet &p)
{
NS_DEBUG_UNCOND("FakeInternetNode::DoPull (" << &p << ")");
return m_dtqOutbound.Dequeue(p);
}
// ===========================================================================
// Cook up a simplistic Physical Layer
// ===========================================================================
class FakePhysicalLayer :
public LayerConnectorLower,
public LayerConnectorUpper
{
public:
FakePhysicalLayer ();
~FakePhysicalLayer ();
protected:
bool LowerDoNotify (LayerConnectorUpper *upper);
bool UpperDoSendUp (Packet &p);
bool UpperDoPull (Packet &p);
DropTailQueue m_dtqInbound;
DropTailQueue m_dtqOutbound;
};
FakePhysicalLayer::FakePhysicalLayer ()
{
NS_DEBUG_UNCOND("FakePhysicalLayer::FakePhysicalLayer ()");
}
FakePhysicalLayer::~FakePhysicalLayer ()
{
NS_DEBUG_UNCOND("FakePhysicalLayer::~FakePhysicalLayer ()");
}
bool
FakePhysicalLayer::LowerDoNotify (LayerConnectorUpper *upper)
{
NS_DEBUG_UNCOND("FakePhysicalLayer::LowerDoNotify ()");
Packet p;
NS_DEBUG_UNCOND("FakePhysicalLayer::LowerDoNotify (): Starting pull");
NS_ASSERT(m_upperPartner);
m_upperPartner->UpperPull(p);
m_dtqOutbound.Enqueue(p);
NS_DEBUG_UNCOND("FakePhysicalLayer::LowerDoNotify (): Got bits, Notify lower");
NS_ASSERT(m_lowerPartner);
return m_lowerPartner->LowerNotify(this);
}
bool
FakePhysicalLayer::UpperDoSendUp (Packet &p)
{
NS_DEBUG_UNCOND("FakePhysicalLayer::UpperDoSendUp (" << &p << ")");
NS_ASSERT(m_upperPartner);
return m_upperPartner->UpperSendUp(p);
}
bool
FakePhysicalLayer::UpperDoPull (Packet &p)
{
NS_DEBUG_UNCOND("FakePhysicalLayer::DoPull (" << &p << ")");
return m_dtqOutbound.Dequeue(p);
}
// ===========================================================================
// Cook up a simplistic Channel, just to add any moby hack we feel like
// ===========================================================================
class FakeChannel : public Channel
{
public:
FakeChannel ();
~FakeChannel ();
};
FakeChannel::FakeChannel ()
{
NS_DEBUG_UNCOND("FakeChannel::FakeChannel ()");
}
FakeChannel::~FakeChannel ()
{
NS_DEBUG_UNCOND("FakeChannel::~FakeChannel ()");
}
int main (int argc, char *argv[])
{
NS_DEBUG_UNCOND("Channel Hackorama");
#if 0
DebugComponentEnable("Queue");
DebugComponentEnable("DropTailQueue");
DebugComponentEnable("LayerConnector");
DebugComponentEnable("Channel");
#endif
FakeInternetNode node1, node2, node3, node4;
FakePhysicalLayer phys1, phys2, phys3, phys4;
FakeChannel channel;
Packet pkt;
// all the hassle above lets us do something very simple here
node1.ConnectToLower(phys1);
phys1.ConnectToUpper(node1);
phys1.ConnectToLower(channel);
channel.ConnectToUpper(phys1);
node2.ConnectToLower(phys2);
phys2.ConnectToUpper(node2);
phys2.ConnectToLower(channel);
channel.ConnectToUpper(phys2);
node3.ConnectToLower(phys3);
phys3.ConnectToUpper(node3);
phys3.ConnectToLower(channel);
channel.ConnectToUpper(phys3);
node4.ConnectToLower(phys4);
phys4.ConnectToUpper(node4);
phys4.ConnectToLower(channel);
channel.ConnectToUpper(phys4);
node1.Doit();
node2.Doit();
node3.Doit();
node4.Doit();
return 0;
}
+38
View File
@@ -0,0 +1,38 @@
#include "ns3/object.h"
#include "ns3/component-manager.h"
using namespace ns3;
class AnObject : public Object
{
public:
static const InterfaceId iid;
static const ClassId cid;
AnObject (int a, double b);
protected:
virtual void DoDispose (void);
};
const InterfaceId AnObject::iid = MakeInterfaceId ("AnObject", Object::iid);
const ClassId AnObject::cid = MakeClassId<AnObject, int, double> ("AnObject", AnObject::iid);
AnObject::AnObject (int a, double b)
{
// enable our interface
SetInterfaceId (AnObject::iid);
}
void
AnObject::DoDispose (void)
{
// Do your work here.
// chain up
Object::DoDispose ();
}
int main (int argc, char *argv[])
{
Ptr<AnObject> anObject = ComponentManager::Create<AnObject,int,double> (AnObject::cid, AnObject::iid, 10, 20.0);
NS_ASSERT (anObject != 0);
return 0;
}
+13
View File
@@ -0,0 +1,13 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
#include "ns3/debug.h"
NS_DEBUG_COMPONENT_DEFINE ("MyComponentB");
namespace foo {
void OneFunction (void)
{
NS_DEBUG ("OneFunction debug");
}
}; // namespace foo
+27
View File
@@ -0,0 +1,27 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
#include "ns3/debug.h"
#include "ns3/assert.h"
NS_DEBUG_COMPONENT_DEFINE ("MyComponentA");
// declare other function
namespace foo {
void OneFunction (void);
}
int main (int argc, int argv)
{
NS_DEBUG ("nargc="<<argc);
foo::OneFunction ();
NS_DEBUG ("other debug output");
int a;
a = 0;
NS_ASSERT (a == 0);
NS_ASSERT_MSG (a == 0, "my msg");
NS_ASSERT (a != 0);
NS_ASSERT_MSG (a != 0, "my 2 msg");
}
+85
View File
@@ -0,0 +1,85 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
#include <string>
#include "ns3/default-value.h"
#include "ns3/command-line.h"
#include "ns3/debug.h"
using namespace ns3;
//
// This sample file demonstrates how to take some simple member
// variables and hook them into the default variable system
// Typically, you will establish a static variable to maintain the current
// value of the default parameter. Then as other code require the values of
// the defaults, they query them with GetValue() to get the present value.
static BooleanDefaultValue defaultTestBool1 ("testBool1", "helpBool", true);
static IntegerDefaultValue<int> defaultTestInt1 ("testInt1", "helpInt1", 33);
static IntegerDefaultValue<uint32_t> defaultTestInt2 ("testInt2", "helpInt2", 47);
//
// This test class demonstrates the declaration of variables that
// may be overridden by the default-value system
//
// You will see in the core ns-3 modules that many member variables
// can be overridden in this manner
//
class TestClass {
public:
TestClass();
virtual ~TestClass () {}
bool m_testBool1;
int m_testInt1;
uint32_t m_testInt2;
};
//
// In the constructor, you can assign default values in the initializer
// list such as below; note that the instance of the created TestClass
// will have the values as dictated by the current value of the default.
// This means that the behavior of this class can be changed on the fly with
// calls to bind.
//
TestClass::TestClass () :
m_testBool1(defaultTestBool1.GetValue()),
m_testInt1(defaultTestInt1.GetValue()),
m_testInt2(defaultTestInt2.GetValue())
{
}
using std::cout;
int main (int argc, char* argv[])
{
//The following allows the default values established so far to be hooked
//into the command line argument processing unit. Essentially, the command
//line processor is aware of the DefaultValues that have been registered, and
//will accept command line overrides of these. The call automatically
//provides a --help option in addition to allowing overrides of defaults.
uint32_t loops = 0;
CommandLine::AddArgValue("loops","a test of the command line",loops);
CommandLine::Parse(argc,argv);
//utilize the loops variable to show that it can be read from the command line
if(loops>0)
{
cout<<"You requested "<<loops<<" iterations of a loop";
for(uint32_t i=0;i<loops;++i)
cout<<"iteration "<<i;
}
// Before objects are instantiated in your simulation script, you have
// the opportunity to overwrite any default value in the system.
// The Bind () method allows you to specify the name (string) of the
// global variable and value (string) to overwrite the default.
// Here, the default value of 33 for testInt1 is overwritten with 57
//
Bind("testInt1", "57");
TestClass* testclass = new TestClass ();
NS_DEBUG_UNCOND("TestBool1 default value (" << testclass->m_testBool1 << ")");
NS_DEBUG_UNCOND("TestInt1 default value (" << testclass->m_testInt1 << ")");
NS_DEBUG_UNCOND("TestInt2 default value (" << testclass->m_testInt2 << ")");
delete testclass;
return 0;
}
+121
View File
@@ -0,0 +1,121 @@
#include "ns3/object.h"
using namespace ns3;
class AnObject : public Object
{
public:
static const InterfaceId iid;
AnObject ();
protected:
virtual void DoDispose (void);
};
const InterfaceId AnObject::iid = MakeInterfaceId ("AnObject", Object::iid);
AnObject::AnObject ()
{
// enable our interface
SetInterfaceId (AnObject::iid);
}
void
AnObject::DoDispose (void)
{
// Do your work here.
// chain up
Object::DoDispose ();
}
class AnotherObject : public Object
{
public:
static const InterfaceId iid;
AnotherObject (int a);
private:
virtual void DoDispose (void);
};
const InterfaceId AnotherObject::iid = MakeInterfaceId ("AnotherObject", Object::iid);
AnotherObject::AnotherObject (int a)
{
// enable our interface
SetInterfaceId (AnotherObject::iid);
}
void
AnotherObject::DoDispose (void)
{
// Do your work here.
// chain up
Object::DoDispose ();
}
class YetAnotherObject : public Object
{
public:
static const InterfaceId iid;
YetAnotherObject (int a);
private:
virtual void DoDispose (void);
};
const InterfaceId YetAnotherObject::iid = MakeInterfaceId ("YetAnotherObject", Object::iid);
YetAnotherObject::YetAnotherObject (int a)
{
// enable our interface
SetInterfaceId (YetAnotherObject::iid);
// aggregated directly to another object.
AddInterface (Create<AnObject> ());
}
void
YetAnotherObject::DoDispose (void)
{
// Do your work here.
// chain up
Object::DoDispose ();
}
int main (int argc, char *argv[])
{
Ptr<Object> p;
Ptr<AnObject> anObject;
Ptr<AnotherObject> anotherObject;
Ptr<YetAnotherObject> yetAnotherObject;
p = Create<AnObject> ();
// p gives you access to AnObject's interface
anObject = p->QueryInterface<AnObject> (AnObject::iid);
NS_ASSERT (anObject != 0);
// p does not give you access to AnotherObject's interface
anotherObject = p->QueryInterface<AnotherObject> (AnotherObject::iid);
NS_ASSERT (anotherObject == 0);
anotherObject = Create<AnotherObject> (1);
// AnotherObject does not give you access to AnObject's interface
anObject = anotherObject->QueryInterface<AnObject> (AnObject::iid);
NS_ASSERT (anObject == 0);
// aggregate the two objects
p->AddInterface (anotherObject);
// p gives you access to AnObject's interface
anObject = p->QueryInterface<AnObject> (AnObject::iid);
NS_ASSERT (anObject != 0);
// p gives you access to AnotherObject's interface
anotherObject = p->QueryInterface<AnotherObject> (AnotherObject::iid);
NS_ASSERT (anotherObject != 0);
yetAnotherObject = Create<YetAnotherObject> (2);
// gives you acess to AnObject interface too.
anObject = yetAnotherObject->QueryInterface<AnObject> (AnObject::iid);
NS_ASSERT (anObject != 0);
return 0;
}
+197
View File
@@ -0,0 +1,197 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2006,2007 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "ns3/packet.h"
#include "ns3/header.h"
#include "ns3/packet-printer.h"
#include "ns3/ipv4-header.h"
#include "ns3/udp-header.h"
using namespace ns3;
// This sample file shows how to use the Packet metadata facility
//
// Packets are stored as ``packed'' data structures, to facilitate
// fragmentation and network emulation. However, when debugging a program,
// or for certain tracing applications, it may be convenient to dump out
// the contents of a packet header in a human-friendly form.
//
// To do this, a few things are needed:
// i) enable the metadata facility (disabled by default, because it causes
// a small performance hit
// ii) decide on whether you want to use a default or customized (you
// provide your own) routine to dump a particular header
//
// This sample steps through two routines; one to use the default
// printing of IPv4 and UDP headers, and one to show a non-default case.
// There is a lot of emphasis in this sample of how this facility
// interacts with packet fragmentation.
void DefaultPrint (void)
{
// We create a packet with 1000 bytes of zero payload
// and add 3 headers to this packet.
Packet p (1000);
Ipv4Header ipv4;
UdpHeader udp;
ipv4.SetSource (Ipv4Address ("192.168.0.1"));
ipv4.SetDestination (Ipv4Address ("192.168.0.2"));
udp.SetSource (1025);
udp.SetDestination (80);
udp.SetPayloadSize (1000);
p.AddHeader (udp);
p.AddHeader (ipv4);
std::cout << "full packet size=" << p.GetSize () << std::endl;
// Here, invoke the default Print routine, directed to std out
p.Print (std::cout);
std::cout << std::endl;
// Now, we fragment our packet in 3 consecutive pieces.
Packet p1 = p.CreateFragment (0, 2);
Packet p2 = p.CreateFragment (2, 1000);
Packet p3 = p.CreateFragment (1002, 26);
std::cout << "fragment1" << std::endl;
p1.Print (std::cout);
std::cout << std::endl;
std::cout << "fragment2" << std::endl;
p2.Print (std::cout);
std::cout << std::endl;
std::cout << "fragment3" << std::endl;
p3.Print (std::cout);
std::cout << std::endl;
// And, finally, we re-aggregate the 3 consecutive pieces.
Packet aggregate = p1;
aggregate.AddAtEnd (p2);
aggregate.AddAtEnd (p3);
std::cout << "aggregated" << std::endl;
aggregate.Print (std::cout);
std::cout << std::endl;
}
// The below functions are used in place of default versions, in the
// non-default case below. For instance, DoPrintIpv4Header will print
// out less IPv4 header information than the default print function
void
DoPrintDefault (std::ostream &os,uint32_t packetUid, uint32_t size,
std::string &name, struct PacketPrinter::FragmentInformation info)
{
os << name <<" (size " << size << " trim_start " << info.start << " trim_end " << info.end << ")";
}
void
DoPrintPayload (std::ostream & os,uint32_t packetUid,uint32_t size,
struct PacketPrinter::FragmentInformation info)
{
os << "PAYLOAD (size " << size << " trim_start " << info.start << " trim_end " << info.end << ")";
}
void
DoPrintIpv4Header (std::ostream &os, uint32_t packetUid, uint32_t size, const Ipv4Header *ipv4)
{
os << "IPV4 " << ipv4->GetSource () << " > " << ipv4->GetDestination ();
}
void
DoPrintIpv4HeaderFragment (std::ostream &os, uint32_t packetUid, uint32_t size,
std::string &name, struct PacketPrinter::FragmentInformation info)
{
os << "IPV4 fragment";
}
// This function walks through a non-default case. A few features of
// the API (defined in common/packet-printer.h) are shown.
//
void NonDefaultPrint (void)
{
// create an adhoc packet printer.
PacketPrinter printer;
// print from first header to last trailer
printer.PrintForward ();
// set a string separator automatically inserted
// between each call to a printing function.
printer.SetSeparator (" - ");
// set the default print function: invoked if no
// specialized function has been provided for a header
// or trailer
printer.AddDefaultPrinter (MakeCallback (&DoPrintDefault));
// set the payload print function
printer.AddPayloadPrinter (MakeCallback (&DoPrintPayload));
// set the print function for the header type Ipv4Header.
printer.AddHeaderPrinter (MakeCallback (&DoPrintIpv4Header),
MakeCallback (&DoPrintIpv4HeaderFragment));
// We create a packet with 1000 bytes of zero payload
Packet p (1000);
Ipv4Header ipv4;
UdpHeader udp;
ipv4.SetSource (Ipv4Address ("192.168.0.1"));
ipv4.SetDestination (Ipv4Address ("192.168.0.2"));
udp.SetSource (1025);
udp.SetDestination (80);
udp.SetPayloadSize (1000);
p.AddHeader (udp);
p.AddHeader (ipv4);
std::cout << "full packet size=" << p.GetSize () << std::endl;
p.Print (std::cout, printer);
std::cout << std::endl;
// fragment our packet in 3 pieces
Packet p1 = p.CreateFragment (0, 2);
Packet p2 = p.CreateFragment (2, 1000);
Packet p3 = p.CreateFragment (1002, 26);
std::cout << "fragment1" << std::endl;
p1.Print (std::cout, printer);
std::cout << std::endl;
std::cout << "fragment2" << std::endl;
p2.Print (std::cout, printer);
std::cout << std::endl;
std::cout << "fragment3" << std::endl;
p3.Print (std::cout, printer);
std::cout << std::endl;
// aggregate all 3 fragments of the original packet
// to reconstruct a copy of the original packet.
Packet aggregate = p1;
aggregate.AddAtEnd (p2);
aggregate.AddAtEnd (p3);
std::cout << "aggregated" << std::endl;
aggregate.Print (std::cout, printer);
std::cout << std::endl;
}
int main (int argc, char *argv[])
{
Packet::EnableMetadata ();
std::cout << "DefaultPrint()" << std::endl;
DefaultPrint ();
std::cout << std::endl << "NonDefaultPrint()" << std::endl;
NonDefaultPrint ();
return 0;
}
+103
View File
@@ -0,0 +1,103 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
#include "ns3/packet.h"
#include "ns3/header.h"
#include <iostream>
using namespace ns3;
/* A sample Header implementation
*/
class MyHeader : public Header {
public:
MyHeader ();
virtual ~MyHeader ();
void SetData (uint16_t data);
uint16_t GetData (void) const;
private:
virtual std::string DoGetName (void) const;
virtual void PrintTo (std::ostream &os) const;
virtual void SerializeTo (Buffer::Iterator start) const;
virtual uint32_t DeserializeFrom (Buffer::Iterator start);
virtual uint32_t GetSerializedSize (void) const;
uint16_t m_data;
};
MyHeader::MyHeader ()
{}
MyHeader::~MyHeader ()
{}
std::string
MyHeader::DoGetName (void) const
{
return "MyHeader";
}
void
MyHeader::PrintTo (std::ostream &os) const
{
os << "MyHeader data=" << m_data << std::endl;
}
uint32_t
MyHeader::GetSerializedSize (void) const
{
return 2;
}
void
MyHeader::SerializeTo (Buffer::Iterator start) const
{
// serialize in head of buffer
start.WriteHtonU16 (m_data);
}
uint32_t
MyHeader::DeserializeFrom (Buffer::Iterator start)
{
// deserialize from head of buffer
m_data = start.ReadNtohU16 ();
return GetSerializedSize ();
}
void
MyHeader::SetData (uint16_t data)
{
m_data = data;
}
uint16_t
MyHeader::GetData (void) const
{
return m_data;
}
/* A sample Tag implementation
*/
struct MyTag {
uint16_t m_streamId;
};
static TagRegistration<struct MyTag> g_MyTagRegistration ("ns3::MyTag", 0);
static void
Receive (Packet p)
{
MyHeader my;
p.RemoveHeader (my);
std::cout << "received data=" << my.GetData () << std::endl;
struct MyTag myTag;
p.PeekTag (myTag);
}
int main (int argc, char *argv[])
{
Packet p;
MyHeader my;
my.SetData (2);
std::cout << "send data=2" << std::endl;
p.AddHeader (my);
struct MyTag myTag;
myTag.m_streamId = 5;
p.AddTag (myTag);
Receive (p);
return 0;
}
+76
View File
@@ -0,0 +1,76 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
#include "ns3/ptr.h"
#include "ns3/object.h"
#include <iostream>
using namespace ns3;
class A : public Object
{
public:
A ();
~A ();
void Method (void);
};
A::A ()
{
std::cout << "A constructor" << std::endl;
}
A::~A()
{
std::cout << "A destructor" << std::endl;
}
void
A::Method (void)
{
std::cout << "A method" << std::endl;
}
static Ptr<A> g_a = 0;
static Ptr<A>
StoreA (Ptr<A> a)
{
Ptr<A> prev = g_a;
g_a = a;
return prev;
}
static void
ClearA (void)
{
g_a = 0;
}
int main (int argc, char *argv[])
{
{
// Create a new object of type A, store it in global
// variable g_a
Ptr<A> a = Create<A> ();
a->Method ();
Ptr<A> prev = StoreA (a);
NS_ASSERT (prev == 0);
}
{
// Create a new object of type A, store it in global
// variable g_a, get a hold on the previous A object.
Ptr<A> a = Create<A> ();
Ptr<A> prev = StoreA (a);
// call method on object
prev->Method ();
// Clear the currently-stored object
ClearA ();
// get the raw pointer and release it.
A *raw = GetPointer (prev);
prev = 0;
raw->Method ();
raw->Unref ();
}
return 0;
}
+280
View File
@@ -0,0 +1,280 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 University of Washington
* Authors: Tom Henderson, Craig Dowell
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "ns3/debug.h"
#include "ns3/object.h"
#include "ns3/component-manager.h"
using namespace ns3;
//
// This sample file shows examples of how to use QueryInterface.
//
// QueryInterface is a templated method of class Object, defined in
// src/core/object.h. ns-3 objects that derive from class Object
// can have QueryInterface invoked on them.
//
// QueryInterface is a type-safe way to ask an object, at run-time,
// "Do you support the interface identified by the given InterfaceId?"
// It avoids deprecated techniques of having to downcast pointers to
// an object to ask questions about its type. One or more interfaces
// may be associated with a given object.
//
// QueryInterface is of most use when working with base class
// pointers of objects that may be subclassed. For instance,
// one may have a pointer to a Node, but not know whether it has
// an IPv4 stack. Another example might be to determine whether
// a Node has an EnergyModel, to which calls to decrement energy
// from the node's battery might be made.
//
//
// Object is the base class for ns-3 node-related objects used at
// the public API. Object provides reference counting implementations
// and the QueryInterface.
//
// A common design paradigm for an ns-3 node object, such as a Queue,
// is that we provide an abstract base class that inherits from
// Object. This class is assigned an interface ID (iid) and
// contains the basic API for objects in this class and subclasses.
// This base class is specialized to provide implementations of
// the object in question (such as a DropTailQueue).
//
// The design pattern commonly used is known as the "non-virtual
// public interface" pattern, whereby the public API for this
// object is a set of public non-virtual functions that forward
// to private virtual functions. The forwarding functions can
// impose pre- and post-conditions on the forwarding call at
// the base class level.
//
// We'll call this base class "AnInterface" in the example below.
//
//
class AnInterface : public Object
{
public:
static const InterfaceId iid;
void methodA (void);
private:
virtual void domethodA (void) = 0;
};
void
AnInterface::methodA (void)
{
// pre-dispatch asserts
NS_DEBUG_UNCOND("AnInterface pre-condition::methodA");
domethodA ();
NS_DEBUG_UNCOND("AnInterface post-condition::methodA\n");
// post-dispatch asserts
}
//
// The below assignment assigns the InterfaceId of the class AnInterface,
// and declares that the parent iid is that of class Object.
//
const InterfaceId AnInterface::iid = MakeInterfaceId ("AnInterface", Object::iid);
//
// AnImplementation is an implementation of the abstract base class
// defined above. It provides implementation for the virtual functions
// in the base class. It defines one ClassId for each constructor,
// and can also provide an interface itself (in this example,
// a methodImpl is available)
//
class AnImplementation : public AnInterface
{
public:
static const InterfaceId iid;
static const ClassId cid;
AnImplementation ();
void methodImpl (void);
private:
virtual void domethodA (void);
};
void
AnImplementation::methodImpl (void)
{
NS_DEBUG_UNCOND("AnImplementation::methodImpl\n");
}
AnImplementation::AnImplementation (void)
{
// enable our interface
SetInterfaceId (AnImplementation::iid);
}
void
AnImplementation::domethodA ()
{
NS_DEBUG_UNCOND("AnImplementation::domethodA");
}
//
// The below assignment assigns the InterfaceId of the class AnImplementation,
// and declares that the parent iid is that of class Object.
//
const InterfaceId AnImplementation::iid =
MakeInterfaceId ("AnImplementation", AnInterface::iid);
//
// The next few lines are used by the component manager. They
// state that the component manager can create a new object
// AnImplementation and return an interface corresponding to
// the AnImplementation iid.
//
const ClassId AnImplementation::cid =
MakeClassId<AnImplementation>
("AnImplementation", AnImplementation::iid);
//
// Extending interfaces
// ==================
// What if AnInterface doesn't provide enough API for your
// object type?
// - if you aren't concerned about backward compatibility and
// don't mind recompiling, you just add new methods to AnInterface
// and recompile.
// - if you want to address backward compatibiliy, or allow part
// of the system to use the old interface, you have to do more.
// You have to declare a new interface with the new functionality.
//
class AnExtendedInterface : public AnInterface
{
public:
static const InterfaceId iid;
void methodB (void);
private:
virtual void domethodB (void) = 0;
};
const InterfaceId AnExtendedInterface::iid =
MakeInterfaceId ("AnExtendedInterface", AnInterface::iid);
//
// Then you need provide an implementation for the virtual
// methods. If you are providing a new implementation for
// everything, the answer is straightforward
//
class ANewImplementation : public AnExtendedInterface
{
public:
static const InterfaceId iid;
static const ClassId cid;
ANewImplementation ();
void methodImpl (void);
private:
virtual void domethodA (void) { /* new-implementation-behavior (); */}
virtual void domethodB (void) { /* new-implementation-behavior (); */}
};
ANewImplementation::ANewImplementation (void)
{
// enable our interface
SetInterfaceId (ANewImplementation::iid);
}
void
ANewImplementation::methodImpl (void)
{
NS_DEBUG_UNCOND("ANewImplementation::methodImpl\n");
}
const InterfaceId ANewImplementation::iid =
MakeInterfaceId ("ANewImplementation", AnExtendedInterface::iid);
//
// If you want to extend an existing implementation, you can use
// the existing class to instantiate an implementation of its
// methods (hasa) and do the following if you can use stuff from
// the existing class.
//
class AnExtendedImplementation : public AnExtendedInterface
{
public:
static const InterfaceId iid;
static const ClassId cid;
AnExtendedImplementation ();
void methodImpl (void) { /* pImpl->methodImpl (); */ }
void methodExtendedImpl (void);
private:
virtual void domethodA (void) { /* new-implementation-behavior (); */}
virtual void domethodB (void) { /* new-implementation-behavior (); */}
Ptr<AnImplementation> pImpl;
};
AnExtendedImplementation::AnExtendedImplementation (void)
{
pImpl = Create<AnImplementation> ();
SetInterfaceId (AnExtendedImplementation::iid);
}
void
AnExtendedImplementation::methodExtendedImpl (void)
{
NS_DEBUG_UNCOND("AnExtendedImplementation::methodExtendedImpl\n");
}
const InterfaceId AnExtendedImplementation::iid =
MakeInterfaceId ("AnExtendedImplementation", AnExtendedInterface::iid);
//
// Inheriting from an existing implementation (isa) and an extended
// interface is tricky, because of the diamond multiple inheritance
// problem. If the pImpl method above is not desirable, it may
// be that the implementation extension could be aggregated.
//
// The extension will not have access to the base implementation,
// so this design pattern may be more appropriate if the extension
// is very modular (e.g., add an EnergyModel to a wireless interface)
//
// EXAMPLE NOT YET PROVIDED
int main (int argc, char *argv[])
{
Ptr<AnInterface> aBase = ComponentManager::Create<AnImplementation>
(AnImplementation::cid, AnInterface::iid);
NS_ASSERT (aBase != 0);
aBase->methodA ();
//aBase->methodImpl (); // XXX won't compile, aBase not right ptr type
Ptr<AnImplementation> aBaseImplPtr =
aBase-> QueryInterface<AnImplementation> (AnImplementation::iid);
aBaseImplPtr->methodImpl ();
aBaseImplPtr->methodA();
// Test symmetric property of QueryInterface
Ptr<AnInterface> aBase2 =
aBaseImplPtr-> QueryInterface<AnInterface> (AnInterface::iid);
aBase2->methodA ();
return 0;
}
+66
View File
@@ -0,0 +1,66 @@
#include <iostream>
#include "ns3/internet-node.h"
#include "ns3/simulator.h"
#include "ns3/socket-factory.h"
#include "ns3/socket.h"
#include "ns3/nstime.h"
using namespace ns3;
static void
GenerateTraffic (Ptr<Socket> socket, uint32_t size)
{
std::cout << "at=" << Simulator::Now ().GetSeconds () << "s, tx bytes=" << size << std::endl;
socket->Send (0, size);
if (size > 0)
{
Simulator::Schedule (Seconds (0.5), &GenerateTraffic, socket, size - 50);
}
else
{
socket->Close ();
}
}
static void
SocketPrinter (Ptr<Socket> socket, uint32_t size, const Ipv4Address &from, uint16_t fromPort)
{
std::cout << "at=" << Simulator::Now ().GetSeconds () << "s, rx bytes=" << size << std::endl;
}
static void
PrintTraffic (Ptr<Socket> socket)
{
socket->RecvDummy (MakeCallback (&SocketPrinter));
}
void
RunSimulation (void)
{
Ptr<Node> a = Create<InternetNode> ();
InterfaceId iid = InterfaceId::LookupByName ("Udp");
Ptr<SocketFactory> socketFactory = a->QueryInterface<SocketFactory> (iid);
Ptr<Socket> sink = socketFactory->CreateSocket ();
sink->Bind (80);
Ptr<Socket> source = socketFactory->CreateSocket ();
source->Connect (Ipv4Address::GetLoopback (), 80);
GenerateTraffic (source, 500);
PrintTraffic (sink);
Simulator::Run ();
Simulator::Destroy ();
}
int main (int argc, char *argv[])
{
RunSimulation ();
return 0;
}
+47
View File
@@ -0,0 +1,47 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
#include "ns3/simulator.h"
#include "ns3/nstime.h"
#include <iostream>
using namespace ns3;
class MyModel {
public:
void Start (void);
private:
void DealWithEvent (double eventValue);
};
void
MyModel::Start (void)
{
Simulator::Schedule (Seconds (10.0),
&MyModel::DealWithEvent,
this, Simulator::Now ().GetSeconds ());
}
void
MyModel::DealWithEvent (double value)
{
std::cout << "Member method received event at " << Simulator::Now ().GetSeconds ()
<< "s started at " << value << "s" << std::endl;
}
static void
random_function (MyModel *model)
{
std::cout << "random function received event at " <<
Simulator::Now ().GetSeconds () << "s" << std::endl;
model->Start ();
}
int main (int argc, char *argv[])
{
MyModel model;
Simulator::Schedule (Seconds (10.0), &random_function, &model);
Simulator::Run ();
Simulator::Destroy ();
}
+43
View File
@@ -0,0 +1,43 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
#include "ns3/test.h"
using namespace ns3;
#ifdef RUN_SELF_TESTS
// declare subclass of base class Test
class MyTest : public Test {
public:
MyTest (bool ok);
virtual ~MyTest ();
virtual bool RunTests (void);
private:
bool m_ok;
};
// implement MyTest
MyTest::MyTest (bool ok)
: Test ("My"),
m_ok (ok)
{}
MyTest::~MyTest ()
{}
bool
MyTest::RunTests (void)
{
return m_ok;
}
// instantiate MyTest once
static MyTest g_my_test = MyTest (true);
#endif /* RUN_SELF_TESTS */
int main (int argc, char *argv[])
{
// run tests
TestManager::EnableVerbose ();
TestManager::RunTests ();
return 0;
}
+61
View File
@@ -0,0 +1,61 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
#include "ns3/trace-container.h"
#include "ns3/ui-variable-tracer.h"
#include "ns3/callback-tracer.h"
#include "ns3/stream-tracer.h"
#include "ns3/pcap-writer.h"
#include "ns3/packet.h"
#include <iostream>
using namespace ns3;
CallbackTraceSourcer<Packet> a;
UiVariableTracer<unsigned short> b;
StreamTracer c;
CallbackTraceSourcer<double, int> d;
void
RegisterAllTraceSources (TraceContainer *container)
{
container->RegisterCallback ("source-a", &a);
container->RegisterUiVariable ("source-b", &b);
container->RegisterStream ("source-c", &c);
container->RegisterCallback ("source-d", &d);
}
void
GenerateTraceEvents (void)
{
// log en empty packet
a (Packet ());
b = 10;
b += 100;
b += 50;
b = (unsigned short) -20;
c << "this is a simple test b=" << b << std::endl;
d (3.1415, 3);
}
void
VariableEvent (uint64_t old, uint64_t cur)
{}
void
CallbackEvent (double a, int b)
{}
int main (int argc, char *argv[])
{
TraceContainer traces;
RegisterAllTraceSources (&traces);
PcapWriter pcap;
pcap.Open ("trace-test.log");
pcap.WriteHeaderEthernet ();
traces.SetCallback ("source-a",
MakeCallback (&PcapWriter::WritePacket, &pcap));
traces.SetUiVariableCallback ("source-b", MakeCallback (&VariableEvent));
traces.SetStream ("source-c", &std::cout);
traces.SetCallback ("source-d", MakeCallback (&CallbackEvent));
GenerateTraceEvents ();
return 0;
}
+53
View File
@@ -0,0 +1,53 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 University of Washington
* 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
*/
#include <string>
#include "ns3/debug.h"
#include "ns3/trace-writer.h"
using namespace ns3;
int main (int argc, char *argv[])
{
NS_DEBUG_UNCOND("TraceWriter Test")
TraceWriter writer1;
writer1.Open("trace-writer-test.txt");
writer1.Write("writer1.char*\n");
writer1.Write(std::string("writer1.string\n"));
writer1.Close();
TraceWriter writer2;
writer2.Open(std::string("trace-writer-test.txt"));
writer2.Write("writer2.char*\n");
writer2.Write(std::string("writer2.string\n"));
writer2.Close();
TraceWriter writer3("trace-writer-test.txt");
writer3.Write("writer3.char*\n");
writer3.Write(std::string("writer3.string\n"));
writer3.Close();
TraceWriter writer4(std::string("trace-writer-test.txt"));
writer4.Write("writer4.char*\n");
writer4.Write(std::string("writer4.string\n"));
writer4.Close();
return 0;
}
+24
View File
@@ -0,0 +1,24 @@
## -*- 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 = ["ns3-%s" % dep for dep in deps]
obj.source = source
return obj
obj = create_ns_prog('main-debug', ['main-debug.cc', 'main-debug-other.cc'])
obj = create_ns_prog('main-callback', 'main-callback.cc')
obj = create_ns_prog('main-ptr', 'main-ptr.cc')
#obj = create_ns_prog('main-trace', 'main-trace.cc')
obj = create_ns_prog('main-simulator', 'main-simulator.cc')
obj = create_ns_prog('main-packet', 'main-packet.cc')
obj = create_ns_prog('main-test', 'main-test.cc')
obj = create_ns_prog('main-simple', 'main-simple.cc',
deps=['node', 'internet-node', 'applications'])
#obj = create_ns_prog('main-simple-p2p', 'main-simple-p2p.cc', deps=['node', 'p2p'])
obj = create_ns_prog('main-default-value', 'main-default-value.cc',
deps=['core', 'simulator', 'node', 'p2p'])
+230
View File
@@ -0,0 +1,230 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
//
// Copyright (c) 2006 Georgia Tech Research Corporation
//
// 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<riley@ece.gatech.edu>
//
// ns3 - On/Off Data Source Application class
// George F. Riley, Georgia Tech, Spring 2007
// Adapted from ApplicationOnOff in GTNetS.
#include "ns3/ipv4-address.h"
#include "ns3/node.h"
#include "ns3/nstime.h"
#include "ns3/data-rate.h"
#include "ns3/random-variable.h"
#include "ns3/socket.h"
#include "ns3/simulator.h"
#include "ns3/socket-factory.h"
#include "ns3/default-value.h"
#include "onoff-application.h"
using namespace std;
namespace ns3 {
// Defaults for rate/size
static DataRateDefaultValue g_defaultRate ("OnOffApplicationDataRate",
"The data rate in on state for OnOffApplication",
DataRate ("500kb/s"));
static IntegerDefaultValue<uint32_t> g_defaultSize ("OnOffApplicationPacketSize",
"The size of packets sent in on state for OnOffApplication",
512, 1);
// Constructors
OnOffApplication::OnOffApplication(Ptr<Node> n,
const Ipv4Address rip,
uint16_t rport,
std::string iid,
const RandomVariable& ontime,
const RandomVariable& offtime)
: Application(n),
m_cbrRate (g_defaultRate.GetValue ())
{
Construct (n, rip, rport, iid,
ontime, offtime,
g_defaultSize.GetValue ());
}
OnOffApplication::OnOffApplication(Ptr<Node> n,
const Ipv4Address rip,
uint16_t rport,
std::string iid,
const RandomVariable& ontime,
const RandomVariable& offtime,
DataRate rate,
uint32_t size)
: Application(n),
m_cbrRate (rate)
{
Construct (n, rip, rport, iid,
ontime, offtime, size);
}
void
OnOffApplication::Construct (Ptr<Node> n,
const Ipv4Address rip,
uint16_t rport,
std::string iid,
const RandomVariable& onTime,
const RandomVariable& offTime,
uint32_t size)
{
m_socket = 0;
m_peerIp = rip;
m_peerPort = rport;
m_connected = false;
m_onTime = onTime.Copy ();
m_offTime = offTime.Copy ();
m_pktSize = size;
m_residualBits = 0;
m_lastStartTime = Seconds (0);
m_maxBytes = 0xffffffff;
m_totBytes = 0;
m_iid = iid;
}
OnOffApplication::~OnOffApplication()
{}
void
OnOffApplication::SetMaxBytes(uint32_t maxBytes)
{
m_maxBytes = maxBytes;
}
void
OnOffApplication::SetDefaultRate (const DataRate &rate)
{
g_defaultRate.SetValue (rate);
}
void
OnOffApplication::SetDefaultSize (uint32_t size)
{
g_defaultSize.SetValue (size);
}
void
OnOffApplication::DoDispose (void)
{
m_socket = 0;
delete m_onTime;
delete m_offTime;
m_onTime = 0;
m_offTime = 0;
// chain up
Application::DoDispose ();
}
// Application Methods
void OnOffApplication::StartApplication() // Called at time specified by Start
{
// Create the socket if not already
if (!m_socket)
{
InterfaceId iid = InterfaceId::LookupByName (m_iid);
Ptr<SocketFactory> socketFactory = GetNode ()->QueryInterface<SocketFactory> (iid);
m_socket = socketFactory->CreateSocket ();
m_socket->Bind ();
m_socket->Connect (m_peerIp, m_peerPort);
}
// Insure no pending event
StopApplication();
// If we are not yet connected, there is nothing to do here
// The ConnectionComplete upcall will start timers at that time
//if (!m_connected) return;
ScheduleStartEvent();
}
void OnOffApplication::StopApplication() // Called at time specified by Stop
{
if (m_sendEvent.IsRunning ())
{ // Cancel the pending send packet event
// Calculate residual bits since last packet sent
Time delta(Simulator::Now() - m_lastStartTime);
m_residualBits += (uint32_t)(m_cbrRate.GetBitRate() * delta.GetSeconds());
}
Simulator::Cancel(m_sendEvent);
Simulator::Cancel(m_startStopEvent);
}
// Event handlers
void OnOffApplication::StartSending()
{
ScheduleNextTx(); // Schedule the send packet event
}
void OnOffApplication::StopSending()
{
Simulator::Cancel(m_sendEvent);
}
// Private helpers
void OnOffApplication::ScheduleNextTx()
{
if (m_totBytes < m_maxBytes)
{
uint32_t bits = m_pktSize * 8 - m_residualBits;
Time nextTime(Seconds (bits /
static_cast<double>(m_cbrRate.GetBitRate()))); // Time till next packet
m_sendEvent = Simulator::Schedule(nextTime, &OnOffApplication::SendPacket, this);
}
else
{ // All done, cancel any pending events
StopApplication();
}
}
void OnOffApplication::ScheduleStartEvent()
{ // Schedules the event to start sending data (switch to the "On" state)
Time offInterval = Seconds(m_offTime->GetValue());
m_startStopEvent = Simulator::Schedule(offInterval, &OnOffApplication::StartSending, this);
}
void OnOffApplication::ScheduleStopEvent()
{ // Schedules the event to stop sending data (switch to "Off" state)
Time onInterval = Seconds(m_onTime->GetValue());
Simulator::Schedule(onInterval, &OnOffApplication::StopSending, this);
}
void OnOffApplication::SendPacket()
{
NS_ASSERT (m_sendEvent.IsExpired ());
m_socket->Send(0, m_pktSize);
m_totBytes += m_pktSize;
m_lastStartTime = Simulator::Now();
m_residualBits = 0;
ScheduleNextTx();
}
void OnOffApplication::ConnectionSucceeded(Ptr<Socket>)
{
m_connected = true;
ScheduleStartEvent();
}
void OnOffApplication::ConnectionFailed(Ptr<Socket>)
{
cout << "OnOffApplication, Connection Failed" << endl;
}
} // Namespace ns3
+157
View File
@@ -0,0 +1,157 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
//
// Copyright (c) 2006 Georgia Tech Research Corporation
//
// 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<riley@ece.gatech.edu>
//
// ns3 - On/Off Data Source Application class
// George F. Riley, Georgia Tech, Spring 2007
// Adapted from ApplicationOnOff in GTNetS.
#ifndef __onoff_application_h__
#define __onoff_application_h__
#include "ns3/application.h"
#include "ns3/event-id.h"
#include "ns3/ptr.h"
namespace ns3 {
class Ipv4Address;
class RandomVariable;
class Socket;
class DataRate;
/**
* \brief Generate traffic to a single destination according to an
* OnOff pattern.
*
* This traffic follows an On/Off pattern: after Application::StartApplication
* is called, "On" and "Off" states alternate. The duration of each of
* these states is determined with the onTime and the offTime random
* variables. During the "Off" state, no traffic is generated.
* During the "On" state, cbr traffic is generated. This cbr traffic is
* characterized by the specified "data rate" and "packet size".
*/
class OnOffApplication : public Application
{
public:
/**
* \param n node associated to this application
* \param rip remote ip address
* \param rport remove port number
* \param iid
* \param ontime on time random variable
* \param offtime off time random variable
*/
OnOffApplication(Ptr<Node> n,
const Ipv4Address rip,
uint16_t rport,
std::string iid,
const RandomVariable& ontime,
const RandomVariable& offtime);
/**
* \param n node associated to this application
* \param rip remote ip address
* \param rport remove port number
* \param iid
* \param ontime on time random variable
* \param offtime off time random variable
* \param rate data rate when on
* \param size size of packets when sending data.
*/
OnOffApplication(Ptr<Node> n,
const Ipv4Address rip,
uint16_t rport,
std::string iid,
const RandomVariable& ontime,
const RandomVariable& offtime,
DataRate rate,
uint32_t size);
virtual ~OnOffApplication();
void SetMaxBytes(uint32_t maxBytes);
/**
* \param r the data rate
*
* Set the data rate to use for every OnOffApplication for which
* the user does not specify an explicit data rate.
*/
static void SetDefaultRate(const DataRate & r);
/**
* \param size the packet size
*
* Set the packet size to use for every OnOffApplication for
* which the user does not specify an explicit packet size.
*/
static void SetDefaultSize (uint32_t size);
protected:
virtual void DoDispose (void);
private:
// inherited from Application base class.
virtual void StartApplication (void); // Called at time specified by Start
virtual void StopApplication (void); // Called at time specified by Stop
void Construct (Ptr<Node> n,
const Ipv4Address rip,
uint16_t rport,
std::string iid,
const RandomVariable& ontime,
const RandomVariable& offtime,
uint32_t size);
// Event handlers
void StartSending();
void StopSending();
void SendPacket();
Ptr<Socket> m_socket; // Associated socket
Ipv4Address m_peerIp; // Peer IP address
uint16_t m_peerPort; // Peer port
bool m_connected; // True if connected
RandomVariable* m_onTime; // rng for On Time
RandomVariable* m_offTime; // rng for Off Time
DataRate m_cbrRate; // Rate that data is generated
uint32_t m_pktSize; // Size of packets
uint32_t m_residualBits; // Number of generated, but not sent, bits
Time m_lastStartTime;// Time last packet sent
uint32_t m_maxBytes; // Limit total number of bytes sent
uint32_t m_totBytes; // Total bytes sent so far
EventId m_startStopEvent; // Event id for next start or stop event
EventId m_sendEvent; // Eventid of pending "send packet" event
bool m_sending; // True if currently in sending state
std::string m_iid;
private:
void ScheduleNextTx();
void ScheduleStartEvent();
void ScheduleStopEvent();
void ConnectionSucceeded(Ptr<Socket>);
void ConnectionFailed(Ptr<Socket>);
void Ignore(Ptr<Socket>);
};
} // namespace ns3
#endif
+15
View File
@@ -0,0 +1,15 @@
## -*- 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.uselib_local = ['ns3-node']
obj.source = [
'onoff-application.cc',
]
headers = bld.create_obj('ns3header')
headers.source = [
'onoff-application.h',
]
+137
View File
@@ -0,0 +1,137 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef ARRAY_TRACE_RESOLVER_H
#define ARRAY_TRACE_RESOLVER_H
#include <stdint.h>
#include <string>
#include "ns3/callback.h"
#include "trace-resolver.h"
namespace ns3 {
/**
* \brief a helper class to offer trace resolution for an array of objects.
* \ingroup lowleveltracing
*/
template <typename T>
class ArrayTraceResolver : public TraceResolver
{
public:
/**
* \brief array index trace context
*
* During namespace parsing, ns3::ArrayTraceResolver will
* embed an instance of this class in the TraceContext
* associated to every child object of the object stored
* at the index.
*
* The reason why this class exists is to ensure that we
* need to ensure that we can store a unique type as context
* into the TraceContext associated to this trace resolver.
*/
class Index
{
public:
Index ();
Index (uint32_t index);
/**
* The Index is automatically convertible to the
* uin32_t type such that it really behaves like a uint32_t
* array index for the user.
*
* \returns the index itself
*/
operator uint32_t ();
private:
uint32_t m_index;
};
/**
* \param context trace context associated to this trace resolver
* \param getSize callback which returns dynamically the size of underlying array
* \param get callback which returns any element in the underlying array
*
* Construct a trace resolver which can match any input integer
* against an element in an array. The array is accessed using a
* pair of callbacks. It is the responsability of the user to
* provide two such callbacks whose job is to adapt the array
* API to the resolver needs. Each element of the array is expected
* to provide a method named CreateTraceResolver which takes as
* only argument a reference to a const TraceContext and returns
* a pointer to a TraceResolver. i.e. the signature is:
* TraceResolver * (*) (TraceContext const &)
*/
ArrayTraceResolver (TraceContext const &context,
Callback<uint32_t> getSize,
Callback<T *, uint32_t> get);
private:
virtual TraceResolverList DoLookup (std::string id) const;
Callback<uint32_t> m_getSize;
Callback<T *, uint32_t> m_get;
};
}//namespace ns3
namespace ns3 {
template <typename T>
ArrayTraceResolver<T>::Index::Index ()
: m_index ()
{}
template <typename T>
ArrayTraceResolver<T>::Index::Index (uint32_t index)
: m_index (index)
{}
template <typename T>
ArrayTraceResolver<T>::Index::operator uint32_t ()
{
return m_index;
}
template <typename T>
ArrayTraceResolver<T>::ArrayTraceResolver (TraceContext const &context,
Callback<uint32_t> getSize,
Callback<T *, uint32_t> get)
: TraceResolver (context),
m_getSize (getSize),
m_get (get)
{}
template <typename T>
TraceResolver::TraceResolverList
ArrayTraceResolver<T>::DoLookup (std::string id) const
{
TraceResolverList list;
if (id == "*")
{
for (uint32_t i = 0; i < m_getSize (); i++)
{
TraceContext context = GetContext ();
typename ArrayTraceResolver<T>::Index index = typename ArrayTraceResolver<T>::Index (i);
context.Add (index);
list.push_back (m_get (i)->CreateTraceResolver (context));
}
}
return list;
}
}//namespace ns3
#endif /* ARRAY_TRACE_RESOLVER_H */
+683
View File
@@ -0,0 +1,683 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2005,2006 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "buffer.h"
#include "ns3/assert.h"
#include <iostream>
//#define TRACE(x) std::cout << x << std::endl;
#define TRACE(x)
namespace ns3 {
Buffer::BufferDataList Buffer::m_freeList;
uint32_t Buffer::m_maxTotalAddStart = 0;
uint32_t Buffer::m_maxTotalAddEnd = 0;
struct Buffer::BufferData *
Buffer::Allocate (uint32_t reqSize, uint32_t reqStart)
{
if (reqSize == 0)
{
reqSize = 1;
}
NS_ASSERT (reqSize >= 1);
uint32_t size = reqSize - 1 + sizeof (struct Buffer::BufferData);
uint8_t *b = new uint8_t [size];
struct BufferData *data = reinterpret_cast<struct Buffer::BufferData*>(b);
data->m_size = reqSize;
data->m_initialStart = reqStart;
data->m_dirtyStart = reqStart;
data->m_dirtySize = 0;
data->m_count = 1;
return data;
}
void
Buffer::Deallocate (struct Buffer::BufferData *data)
{
uint8_t *buf = reinterpret_cast<uint8_t *> (data);
delete [] buf;
}
#ifdef USE_FREE_LIST
void
Buffer::Recycle (struct Buffer::BufferData *data)
{
NS_ASSERT (data->m_count == 0);
/* get rid of it if it is too small for later reuse. */
if (data->m_size < (Buffer::m_maxTotalAddStart + Buffer::m_maxTotalAddEnd))
{
Buffer::Deallocate (data);
return;
}
/* feed into free list */
if (Buffer::m_freeList.size () > 1000)
{
Buffer::Deallocate (data);
}
else
{
Buffer::m_freeList.push_back (data);
}
}
Buffer::BufferData *
Buffer::Create (void)
{
/* try to find a buffer correctly sized. */
while (!Buffer::m_freeList.empty ())
{
struct Buffer::BufferData *data = Buffer::m_freeList.back ();
Buffer::m_freeList.pop_back ();
if (data->m_size >= (m_maxTotalAddStart + m_maxTotalAddEnd))
{
data->m_initialStart = m_maxTotalAddStart;
data->m_dirtyStart = m_maxTotalAddStart;
data->m_dirtySize = 0;
data->m_count = 1;
return data;
}
Buffer::Deallocate (data);
}
struct Buffer::BufferData *data = Buffer::Allocate (m_maxTotalAddStart+m_maxTotalAddEnd,
m_maxTotalAddStart);
NS_ASSERT (data->m_count == 1);
return data;
}
#else
void
Buffer::Recycle (struct Buffer::BufferData *data)
{
Buffer::Deallocate (data);
}
Buffer::BufferData *
Buffer::Create (void)
{
return Buffer::Allocate (m_maxTotalAddStart+m_maxTotalAddEnd,
m_maxTotalAddStart);
}
#endif
}; // namespace ns3
#include "ns3/assert.h"
namespace ns3 {
void
Buffer::AddAtStart (uint32_t start)
{
NS_ASSERT (m_start <= m_data->m_initialStart);
bool isDirty = m_data->m_count > 1 && m_start > m_data->m_dirtyStart;
if (m_start >= start && !isDirty)
{
/* enough space in the buffer and not dirty. */
m_start -= start;
m_size += start;
}
else if (m_size + start <= m_data->m_size && !isDirty)
{
/* enough space but need to move data around to fit new data */
memmove (m_data->m_data + start, GetStart (), m_size);
NS_ASSERT (start > m_start);
m_data->m_initialStart += start - m_start;
m_start = 0;
m_size += start;
}
else if (m_start < start)
{
/* not enough space in buffer */
uint32_t newSize = m_size + start;
struct Buffer::BufferData *newData = Buffer::Allocate (newSize, 0);
memcpy (newData->m_data + start, GetStart (), m_size);
newData->m_initialStart = m_data->m_initialStart + start;
m_data->m_count--;
if (m_data->m_count == 0)
{
Buffer::Deallocate (m_data);
}
m_data = newData;
m_start = 0;
m_size = newSize;
}
else
{
/* enough space in the buffer but it is dirty ! */
NS_ASSERT (isDirty);
struct Buffer::BufferData *newData = Buffer::Create ();
memcpy (newData->m_data + m_start, GetStart (), m_size);
newData->m_initialStart = m_data->m_initialStart;
m_data->m_count--;
if (m_data->m_count == 0)
{
Recycle (m_data);
}
m_data = newData;
m_start -= start;
m_size += start;
}
// update dirty area
m_data->m_dirtyStart = m_start;
m_data->m_dirtySize = m_size;
// update m_maxTotalAddStart
uint32_t addedAtStart;
if (m_data->m_initialStart > m_start)
{
addedAtStart = m_data->m_initialStart - m_start;
}
else
{
addedAtStart = 0;
}
if (addedAtStart > m_maxTotalAddStart)
{
m_maxTotalAddStart = addedAtStart;
}
TRACE ("start add="<<start<<", start="<<m_start<<", size="<<m_size<<", zero="<<m_zeroAreaSize<<
", real size="<<m_data->m_size<<", ini start="<<m_data->m_initialStart<<
", dirty start="<<m_data->m_dirtyStart<<", dirty size="<<m_data->m_dirtySize);
}
void
Buffer::AddAtEnd (uint32_t end)
{
NS_ASSERT (m_start <= m_data->m_initialStart);
bool isDirty = m_data->m_count > 1 &&
m_start + m_size < m_data->m_dirtyStart + m_data->m_dirtySize;
if (m_start + m_size + end <= m_data->m_size && !isDirty)
{
/* enough space in buffer and not dirty */
m_size += end;
}
else if (m_size + end <= m_data->m_size && !isDirty)
{
/* enough space but need to move data around to fit the extra data */
uint32_t newStart = m_data->m_size - (m_size + end);
memmove (m_data->m_data + newStart, GetStart (), m_size);
NS_ASSERT (newStart < m_start);
m_data->m_initialStart -= m_start - newStart;
m_start = newStart;
m_size += end;
}
else if (m_start + m_size + end > m_data->m_size)
{
/* not enough space in buffer */
uint32_t newSize = m_size + end;
struct Buffer::BufferData *newData = Buffer::Allocate (newSize, 0);
memcpy (newData->m_data, GetStart (), m_size);
newData->m_initialStart = m_data->m_initialStart - m_start;
m_data->m_count--;
if (m_data->m_count == 0)
{
Buffer::Deallocate (m_data);
}
m_data = newData;
m_size = newSize;
m_start = 0;
}
else
{
/* enough space in the buffer but it is dirty ! */
NS_ASSERT (isDirty);
struct Buffer::BufferData *newData = Buffer::Create ();
memcpy (newData->m_data + m_start, GetStart (), m_size);
newData->m_initialStart = m_data->m_initialStart;
m_data->m_count--;
if (m_data->m_count == 0)
{
Recycle (m_data);
}
m_data = newData;
m_size += end;
}
// update dirty area
m_data->m_dirtyStart = m_start;
m_data->m_dirtySize = m_size;
// update m_maxTotalAddEnd
uint32_t endLoc = m_start + m_size;
uint32_t addedAtEnd;
if (m_data->m_initialStart < endLoc)
{
addedAtEnd = endLoc - m_data->m_initialStart;
}
else
{
addedAtEnd = 0;
}
if (addedAtEnd > m_maxTotalAddEnd)
{
m_maxTotalAddEnd = addedAtEnd;
}
TRACE ("end add="<<end<<", start="<<m_start<<", size="<<m_size<<", zero="<<m_zeroAreaSize<<
", real size="<<m_data->m_size<<", ini start="<<m_data->m_initialStart<<
", dirty start="<<m_data->m_dirtyStart<<", dirty size="<<m_data->m_dirtySize);
}
void
Buffer::RemoveAtStart (uint32_t start)
{
if (m_zeroAreaSize == 0)
{
if (m_size <= start)
{
m_start += m_size;
m_size = 0;
}
else
{
m_start += start;
m_size -= start;
}
}
else
{
NS_ASSERT (m_data->m_initialStart >= m_start);
uint32_t zeroStart = m_data->m_initialStart - m_start;
uint32_t zeroEnd = zeroStart + m_zeroAreaSize;
uint32_t dataEnd = m_size + m_zeroAreaSize;
if (start <= zeroStart)
{
/* only remove start of buffer */
m_start += start;
m_size -= start;
}
else if (start <= zeroEnd)
{
/* remove start of buffer _and_ start of zero area */
m_start += zeroStart;
uint32_t zeroDelta = start - zeroStart;
m_zeroAreaSize -= zeroDelta;
NS_ASSERT (zeroDelta <= start);
m_size -= zeroStart;
}
else if (start <= dataEnd)
{
/* remove start of buffer, complete zero area, and part
* of end of buffer */
m_start += start - m_zeroAreaSize;
m_size -= start - m_zeroAreaSize;
m_zeroAreaSize = 0;
}
else
{
/* remove all buffer */
m_start += m_size;
m_size = 0;
m_zeroAreaSize = 0;
}
}
TRACE ("start remove="<<start<<", start="<<m_start<<", size="<<m_size<<
", zero="<<m_zeroAreaSize<<
", real size="<<m_data->m_size<<", ini start="<<m_data->m_initialStart<<
", dirty start="<<m_data->m_dirtyStart<<", dirty size="<<m_data->m_dirtySize);
}
void
Buffer::RemoveAtEnd (uint32_t end)
{
if (m_zeroAreaSize == 0)
{
if (m_size <= end)
{
m_size = 0;
}
else
{
m_size -= end;
}
}
else
{
NS_ASSERT (m_data->m_initialStart >= m_start);
uint32_t zeroStart = m_data->m_initialStart - m_start;
uint32_t zeroEnd = zeroStart + m_zeroAreaSize;
uint32_t dataEnd = m_size + m_zeroAreaSize;
NS_ASSERT (zeroStart <= m_size);
NS_ASSERT (zeroEnd <= m_size + m_zeroAreaSize);
if (dataEnd <= end)
{
/* remove all buffer */
m_zeroAreaSize = 0;
m_start += m_size;
m_size = 0;
}
else if (dataEnd - zeroStart <= end)
{
/* remove end of buffer, zero area, part of start of buffer */
NS_ASSERT (end >= m_zeroAreaSize);
m_size -= end - m_zeroAreaSize;
m_zeroAreaSize = 0;
}
else if (dataEnd - zeroEnd <= end)
{
/* remove end of buffer, part of zero area */
uint32_t zeroDelta = end - (dataEnd - zeroEnd);
m_zeroAreaSize -= zeroDelta;
m_size -= end - zeroDelta;
}
else
{
/* remove part of end of buffer */
m_size -= end;
}
}
TRACE ("end remove="<<end<<", start="<<m_start<<", size="<<m_size<<", zero="<<m_zeroAreaSize<<
", real size="<<m_data->m_size<<", ini start="<<m_data->m_initialStart<<
", dirty start="<<m_data->m_dirtyStart<<", dirty size="<<m_data->m_dirtySize);
}
Buffer
Buffer::CreateFragment (uint32_t start, uint32_t length) const
{
uint32_t zeroStart = m_data->m_initialStart - m_start;
uint32_t zeroEnd = zeroStart + m_zeroAreaSize;
if (m_zeroAreaSize != 0 &&
start + length > zeroStart &&
start <= zeroEnd)
{
TransformIntoRealBuffer ();
}
Buffer tmp = *this;
tmp.RemoveAtStart (start);
tmp.RemoveAtEnd (GetSize () - (start + length));
return tmp;
}
void
Buffer::TransformIntoRealBuffer (void) const
{
if (m_zeroAreaSize != 0)
{
NS_ASSERT (m_data->m_initialStart >= m_start);
NS_ASSERT (m_size >= (m_data->m_initialStart - m_start));
Buffer tmp;
tmp.AddAtStart (m_zeroAreaSize);
tmp.Begin ().WriteU8 (0, m_zeroAreaSize);
uint32_t dataStart = m_data->m_initialStart - m_start;
tmp.AddAtStart (dataStart);
tmp.Begin ().Write (m_data->m_data+m_start, dataStart);
uint32_t dataEnd = m_size - (m_data->m_initialStart - m_start);
tmp.AddAtEnd (dataEnd);
Buffer::Iterator i = tmp.End ();
i.Prev (dataEnd);
i.Write (m_data->m_data+m_data->m_initialStart,dataEnd);
*const_cast<Buffer *> (this) = tmp;
}
}
uint8_t const*
Buffer::PeekData (void) const
{
TransformIntoRealBuffer ();
return m_data->m_data + m_start;
}
}; // namespace ns3
#ifdef RUN_SELF_TESTS
#include "ns3/test.h"
#include <iomanip>
namespace ns3 {
class BufferTest: public Test {
private:
bool EnsureWrittenBytes (Buffer b, uint32_t n, uint8_t array[]);
public:
virtual bool RunTests (void);
BufferTest ();
};
BufferTest::BufferTest ()
: Test ("Buffer") {}
bool
BufferTest::EnsureWrittenBytes (Buffer b, uint32_t n, uint8_t array[])
{
bool success = true;
uint8_t *expected = array;
uint8_t const*got;
got = b.PeekData ();
for (uint32_t j = 0; j < n; j++)
{
if (got[j] != expected[j])
{
success = false;
}
}
if (!success)
{
Failure () << "Buffer -- ";
Failure () << "expected: n=";
Failure () << n << ", ";
Failure ().setf (std::ios::hex, std::ios::basefield);
for (uint32_t j = 0; j < n; j++)
{
Failure () << (uint16_t)expected[j] << " ";
}
Failure ().setf (std::ios::dec, std::ios::basefield);
Failure () << "got: ";
Failure ().setf (std::ios::hex, std::ios::basefield);
for (uint32_t j = 0; j < n; j++)
{
Failure () << (uint16_t)got[j] << " ";
}
Failure () << std::endl;
}
return success;
}
/* Note: works only when variadic macros are
* available which is the case for gcc.
* XXX
*/
#define ENSURE_WRITTEN_BYTES(buffer, n, ...) \
{ \
uint8_t bytes[] = {__VA_ARGS__}; \
if (!EnsureWrittenBytes (buffer, n , bytes)) \
{ \
ok = false; \
} \
}
bool
BufferTest::RunTests (void)
{
bool ok = true;
Buffer buffer;
Buffer::Iterator i;
buffer.AddAtStart (6);
i = buffer.Begin ();
i.WriteU8 (0x66);
ENSURE_WRITTEN_BYTES (buffer, 1, 0x66);
i = buffer.Begin ();
i.WriteU8 (0x67);
ENSURE_WRITTEN_BYTES (buffer, 1, 0x67);
i.WriteHtonU16 (0x6568);
i = buffer.Begin ();
ENSURE_WRITTEN_BYTES (buffer, 3, 0x67, 0x65, 0x68);
i.WriteHtonU16 (0x6369);
ENSURE_WRITTEN_BYTES (buffer, 3, 0x63, 0x69, 0x68);
i.WriteHtonU32 (0xdeadbeaf);
ENSURE_WRITTEN_BYTES (buffer, 6, 0x63, 0x69, 0xde, 0xad, 0xbe, 0xaf);
buffer.AddAtStart (2);
i = buffer.Begin ();
i.WriteU16 (0);
ENSURE_WRITTEN_BYTES (buffer, 8, 0, 0, 0x63, 0x69, 0xde, 0xad, 0xbe, 0xaf);
buffer.AddAtEnd (2);
i = buffer.Begin ();
i.Next (8);
i.WriteU16 (0);
ENSURE_WRITTEN_BYTES (buffer, 10, 0, 0, 0x63, 0x69, 0xde, 0xad, 0xbe, 0xaf, 0, 0);
buffer.RemoveAtStart (3);
i = buffer.Begin ();
ENSURE_WRITTEN_BYTES (buffer, 7, 0x69, 0xde, 0xad, 0xbe, 0xaf, 0, 0);
buffer.RemoveAtEnd (4);
i = buffer.Begin ();
ENSURE_WRITTEN_BYTES (buffer, 3, 0x69, 0xde, 0xad);
buffer.AddAtStart (1);
i = buffer.Begin ();
i.WriteU8 (0xff);
ENSURE_WRITTEN_BYTES (buffer, 4, 0xff, 0x69, 0xde, 0xad);
buffer.AddAtEnd (1);
i = buffer.Begin ();
i.Next (4);
i.WriteU8 (0xff);
i.Prev (2);
uint16_t saved = i.ReadU16 ();
i.Prev (2);
i.WriteHtonU16 (0xff00);
i.Prev (2);
if (i.ReadNtohU16 () != 0xff00)
{
ok = false;
}
i.Prev (2);
i.WriteU16 (saved);
ENSURE_WRITTEN_BYTES (buffer, 5, 0xff, 0x69, 0xde, 0xad, 0xff);
Buffer o = buffer;
ENSURE_WRITTEN_BYTES (o, 5, 0xff, 0x69, 0xde, 0xad, 0xff);
o.AddAtStart (1);
i = o.Begin ();
i.WriteU8 (0xfe);
ENSURE_WRITTEN_BYTES (o, 6, 0xfe, 0xff, 0x69, 0xde, 0xad, 0xff);
buffer.AddAtStart (2);
i = buffer.Begin ();
i.WriteU8 (0xfd);
i.WriteU8 (0xfd);
ENSURE_WRITTEN_BYTES (o, 6, 0xfe, 0xff, 0x69, 0xde, 0xad, 0xff);
ENSURE_WRITTEN_BYTES (buffer, 7, 0xfd, 0xfd, 0xff, 0x69, 0xde, 0xad, 0xff);
// test self-assignment
{
Buffer a = o;
a = a;
}
// test Remove start.
buffer = Buffer (5);
ENSURE_WRITTEN_BYTES (buffer, 5, 0, 0, 0, 0, 0);
buffer.RemoveAtStart (1);
ENSURE_WRITTEN_BYTES (buffer, 4, 0, 0, 0, 0);
buffer.AddAtStart (1);
buffer.Begin ().WriteU8 (0xff);
ENSURE_WRITTEN_BYTES (buffer, 5, 0xff, 0, 0, 0, 0);
buffer.RemoveAtStart(3);
ENSURE_WRITTEN_BYTES (buffer, 2, 0, 0);
buffer.AddAtStart (4);
buffer.Begin ().WriteHtonU32 (0xdeadbeaf);
ENSURE_WRITTEN_BYTES (buffer, 6, 0xde, 0xad, 0xbe, 0xaf, 0, 0);
buffer.RemoveAtStart (2);
ENSURE_WRITTEN_BYTES (buffer, 4, 0xbe, 0xaf, 0, 0);
buffer.AddAtEnd (4);
i = buffer.Begin ();
i.Next (4);
i.WriteHtonU32 (0xdeadbeaf);
ENSURE_WRITTEN_BYTES (buffer, 8, 0xbe, 0xaf, 0, 0, 0xde, 0xad, 0xbe, 0xaf);
buffer.RemoveAtStart (5);
ENSURE_WRITTEN_BYTES (buffer, 3, 0xad, 0xbe, 0xaf);
// test Remove end
buffer = Buffer (5);
ENSURE_WRITTEN_BYTES (buffer, 5, 0, 0, 0, 0, 0);
buffer.RemoveAtEnd (1);
ENSURE_WRITTEN_BYTES (buffer, 4, 0, 0, 0, 0);
buffer.AddAtEnd (2);
i = buffer.Begin ();
i.Next (4);
i.WriteU8 (0xab);
i.WriteU8 (0xac);
ENSURE_WRITTEN_BYTES (buffer, 6, 0, 0, 0, 0, 0xab, 0xac);
buffer.RemoveAtEnd (1);
ENSURE_WRITTEN_BYTES (buffer, 5, 0, 0, 0, 0, 0xab);
buffer.RemoveAtEnd (3);
ENSURE_WRITTEN_BYTES (buffer, 2, 0, 0);
buffer.AddAtEnd (6);
i = buffer.Begin ();
i.Next (2);
i.WriteU8 (0xac);
i.WriteU8 (0xad);
i.WriteU8 (0xae);
i.WriteU8 (0xaf);
i.WriteU8 (0xba);
i.WriteU8 (0xbb);
ENSURE_WRITTEN_BYTES (buffer, 8, 0, 0, 0xac, 0xad, 0xae, 0xaf, 0xba, 0xbb);
buffer.AddAtStart (3);
i = buffer.Begin ();
i.WriteU8 (0x30);
i.WriteU8 (0x31);
i.WriteU8 (0x32);
ENSURE_WRITTEN_BYTES (buffer, 11, 0x30, 0x31, 0x32, 0, 0, 0xac, 0xad, 0xae, 0xaf, 0xba, 0xbb);
buffer.RemoveAtEnd (9);
ENSURE_WRITTEN_BYTES (buffer, 2, 0x30, 0x31);
buffer = Buffer (3);
buffer.AddAtEnd (2);
i = buffer.Begin ();
i.Next (3);
i.WriteHtonU16 (0xabcd);
buffer.AddAtStart (1);
buffer.Begin ().WriteU8 (0x21);
ENSURE_WRITTEN_BYTES (buffer, 6, 0x21, 0, 0, 0, 0xab, 0xcd);
buffer.RemoveAtEnd (8);
if (buffer.GetSize () != 0)
{
ok = false;
}
buffer = Buffer (6);
buffer.AddAtStart (9);
buffer.AddAtEnd (3);
i = buffer.End ();
i.Prev (1);
i.WriteU8 (1, 1);
buffer = Buffer (6);
buffer.AddAtStart (3);
buffer.RemoveAtEnd (8);
buffer.AddAtEnd (4);
i = buffer.End ();
i.Prev (4);
i.WriteU8 (1, 4);
buffer = Buffer (1);
buffer.AddAtEnd (100);
i = buffer.End ();
i.Prev (100);
i.WriteU8 (1, 100);
return ok;
}
static BufferTest gBufferTest;
}; // namespace ns3
#endif /* RUN_SELF_TESTS */
+708
View File
@@ -0,0 +1,708 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2005,2006 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef BUFFER_H
#define BUFFER_H
#include <stdint.h>
#include <vector>
namespace ns3 {
/**
* \brief automatically resized byte buffer
*
* This represents a buffer of bytes. Its size is
* automatically adjusted to hold any data prepended
* or appended by the user. Its implementation is optimized
* to ensure that the number of buffer resizes is minimized,
* by creating new Buffers of the maximum size ever used.
* The correct maximum size is learned at runtime during use by
* recording the maximum size of each packet.
*/
class Buffer {
public:
/**
* \brief iterator in a Buffer instance
*/
class Iterator {
public:
inline Iterator ();
/**
* go forward by one byte
*/
inline void Next (void);
/**
* go backward by one byte
*/
inline void Prev (void);
/**
* \param delta number of bytes to go forward
*/
inline void Next (uint32_t delta);
/**
* \param delta number of bytes to go backward
*/
inline void Prev (uint32_t delta);
/**
* \param o the second iterator
* \return number of bytes included between the two iterators
*
* This method works only if the two iterators point
* to the same underlying buffer. Debug builds ensure
* this with an assert.
*/
inline int32_t GetDistanceFrom (Iterator const &o) const;
/**
* \return true if this iterator points to the end of the byte array.
* false otherwise.
*/
inline bool IsEnd (void) const;
/**
* \return true if this iterator points to the start of the byte array.
* false otherwise.
*/
inline bool IsStart (void) const;
/**
* \param data data to write in buffer
*
* Write the data in buffer and avance the iterator position
* by one byte.
*/
inline void WriteU8 (uint8_t data);
/**
* \param data data to write in buffer
* \param len number of times data must be written in buffer
*
* Write the data in buffer len times and avance the iterator position
* by len byte.
*/
inline void WriteU8 (uint8_t data, uint32_t len);
/**
* \param data data to write in buffer
*
* Write the data in buffer and avance the iterator position
* by two bytes. The format of the data written in the byte
* buffer is non-portable. We only ensure that readU16 will
* return exactly what we wrote with writeU16 if the program
* is run on the same machine.
*/
inline void WriteU16 (uint16_t data);
/**
* \param data data to write in buffer
*
* Write the data in buffer and avance the iterator position
* by four bytes. The format of the data written in the byte
* buffer is non-portable. We only ensure that readU32 will
* return exactly what we wrote with writeU32 if the program
* is run on the same machine.
*/
inline void WriteU32 (uint32_t data);
/**
* \param data data to write in buffer
*
* Write the data in buffer and avance the iterator position
* by eight bytes. The format of the data written in the byte
* buffer is non-portable. We only ensure that readU64 will
* return exactly what we wrote with writeU64 if the program
* is run on the same machine.
*/
inline void WriteU64 (uint64_t data);
/**
* \param data data to write in buffer
*
* Write the data in buffer and avance the iterator position
* by two bytes. The data is written in network order and the
* input data is expected to be in host order.
*/
inline void WriteHtonU16 (uint16_t data);
/**
* \param data data to write in buffer
*
* Write the data in buffer and avance the iterator position
* by four bytes. The data is written in network order and the
* input data is expected to be in host order.
*/
inline void WriteHtonU32 (uint32_t data);
/**
* \param data data to write in buffer
*
* Write the data in buffer and avance the iterator position
* by eight bytes. The data is written in network order and the
* input data is expected to be in host order.
*/
inline void WriteHtonU64 (uint64_t data);
/**
* \param buffer a byte buffer to copy in the internal buffer.
* \param size number of bytes to copy.
*
* Write the data in buffer and avance the iterator position
* by size bytes.
*/
inline void Write (uint8_t const*buffer, uint16_t size);
/**
* \param start the start of the data to copy
* \param end the end of the data to copy
*
* Write the data delimited by start and end in internal buffer
* and avance the iterator position by the number of bytes
* copied.
* The input interators _must_ not point to the same Buffer as
* we do to avoid overlapping copies. This is enforced
* in debug builds by asserts.
*/
inline void Write (Iterator start, Iterator end);
/**
* \return the byte read in the buffer.
*
* Read data and advance the Iterator by the number of bytes
* read.
*/
inline uint8_t ReadU8 (void);
/**
* \return the two bytes read in the buffer.
*
* Read data and advance the Iterator by the number of bytes
* read.
* The data is read in the format written by writeU16.
*/
inline uint16_t ReadU16 (void);
/**
* \return the four bytes read in the buffer.
*
* Read data and advance the Iterator by the number of bytes
* read.
* The data is read in the format written by writeU32.
*/
inline uint32_t ReadU32 (void);
/**
* \return the eight bytes read in the buffer.
*
* Read data and advance the Iterator by the number of bytes
* read.
* The data is read in the format written by writeU64.
*/
inline uint64_t ReadU64 (void);
/**
* \return the two bytes read in the buffer.
*
* Read data and advance the Iterator by the number of bytes
* read.
* The data is read in network format and return in host format.
*/
inline uint16_t ReadNtohU16 (void);
/**
* \return the four bytes read in the buffer.
*
* Read data and advance the Iterator by the number of bytes
* read.
* The data is read in network format and return in host format.
*/
inline uint32_t ReadNtohU32 (void);
/**
* \return the eight bytes read in the buffer.
*
* Read data and advance the Iterator by the number of bytes
* read.
* The data is read in network format and return in host format.
*/
inline uint64_t ReadNtohU64 (void);
/**
* \param buffer buffer to copy data into
* \param size number of bytes to copy
*
* Copy size bytes of data from the internal buffer to the
* input buffer and avance the Iterator by the number of
* bytes read.
*/
inline void Read (uint8_t *buffer, uint16_t size);
private:
friend class Buffer;
inline Iterator (Buffer const*buffer, uint32_t m_current);
inline uint32_t GetIndex (uint32_t n);
uint32_t m_zeroStart;
uint32_t m_zeroEnd;
uint32_t m_dataEnd;
uint32_t m_current;
uint8_t *m_data;
};
/**
* \return the number of bytes stored in this buffer.
*/
inline uint32_t GetSize (void) const;
/**
* \return a pointer to the start of the internal
* byte buffer.
*
* The returned pointer points to an area of
* memory which is ns3::Buffer::GetSize () bytes big.
* Please, try to never ever use this method. It is really
* evil and is present only for a few specific uses.
*/
uint8_t const*PeekData (void) const;
/**
* \param start size to reserve
*
* Add bytes at the start of the Buffer. The
* content of these bytes is undefined but debugging
* builds initialize them to 0x33.
* Any call to this method invalidates any Iterator
* pointing to this Buffer.
*/
void AddAtStart (uint32_t start);
/**
* \param end size to reserve
*
* Add bytes at the end of the Buffer. The
* content of these bytes is undefined but debugging
* builds initialize them to 0x33.
* Any call to this method invalidates any Iterator
* pointing to this Buffer.
*/
void AddAtEnd (uint32_t end);
/**
* \param start size to remove
*
* Remove bytes at the start of the Buffer.
* Any call to this method invalidates any Iterator
* pointing to this Buffer.
*/
void RemoveAtStart (uint32_t start);
/**
* \param end size to remove
*
* Remove bytes at the end of the Buffer.
* Any call to this method invalidates any Iterator
* pointing to this Buffer.
*/
void RemoveAtEnd (uint32_t end);
/**
* \param start offset from start of packet
* \param length
*
* \return a fragment of size length starting at offset
* start.
*/
Buffer CreateFragment (uint32_t start, uint32_t length) const;
/**
* \return an Iterator which points to the
* start of this Buffer.
*/
inline Buffer::Iterator Begin (void) const;
/**
* \return an Iterator which points to the
* end of this Buffer.
*/
inline Buffer::Iterator End (void) const;
void TransformIntoRealBuffer (void) const;
inline Buffer (Buffer const &o);
inline Buffer &operator = (Buffer const &o);
inline Buffer ();
inline Buffer (uint32_t dataSize);
inline ~Buffer ();
private:
struct BufferData {
uint32_t m_count;
uint32_t m_size;
uint32_t m_initialStart;
uint32_t m_dirtyStart;
uint32_t m_dirtySize;
uint8_t m_data[1];
};
typedef std::vector<struct Buffer::BufferData*> BufferDataList;
inline uint8_t *GetStart (void) const;
static void Recycle (struct Buffer::BufferData *data);
static struct Buffer::BufferData *Create (void);
static struct Buffer::BufferData *Allocate (uint32_t size, uint32_t start);
static void Deallocate (struct Buffer::BufferData *data);
static BufferDataList m_freeList;
static uint32_t m_maxTotalAddStart;
static uint32_t m_maxTotalAddEnd;
struct BufferData *m_data;
uint32_t m_zeroAreaSize;
uint32_t m_start;
uint32_t m_size;
};
}; // namespace ns3
/**************************************************
Start of implementation of methods which
need to be inline for performance reasons.
*************************************************/
#include "ns3/assert.h"
namespace ns3 {
Buffer::Buffer ()
: m_data (Buffer::Create ()),
m_zeroAreaSize (0),
m_start (m_maxTotalAddStart),
m_size (0)
{
if (m_start > m_data->m_size)
{
m_start = 0;
}
NS_ASSERT (m_start <= m_data->m_size);
}
Buffer::Buffer (uint32_t dataSize)
: m_data (Buffer::Create ()),
m_zeroAreaSize (dataSize),
m_start (m_maxTotalAddStart),
m_size (0)
{
if (m_start > m_data->m_size)
{
m_start = 0;
}
NS_ASSERT (m_start <= m_data->m_size);
}
Buffer::Buffer (Buffer const&o)
: m_data (o.m_data),
m_zeroAreaSize (o.m_zeroAreaSize),
m_start (o.m_start),
m_size (o.m_size)
{
m_data->m_count++;
NS_ASSERT (m_start <= m_data->m_size);
}
Buffer &
Buffer::operator = (Buffer const&o)
{
if (m_data != o.m_data)
{
// not assignment to self.
m_data->m_count--;
if (m_data->m_count == 0)
{
Recycle (m_data);
}
m_data = o.m_data;
m_data->m_count++;
}
m_zeroAreaSize = o.m_zeroAreaSize;
m_start = o.m_start;
m_size = o.m_size;
NS_ASSERT (m_start <= m_data->m_size);
return *this;
}
Buffer::~Buffer ()
{
m_data->m_count--;
if (m_data->m_count == 0)
{
Recycle (m_data);
}
}
uint8_t *
Buffer::GetStart (void) const
{
return m_data->m_data + m_start;
}
uint32_t
Buffer::GetSize (void) const
{
return m_size + m_zeroAreaSize;
}
Buffer::Iterator
Buffer::Begin (void) const
{
return Buffer::Iterator (this, 0);
}
Buffer::Iterator
Buffer::End (void) const
{
return Buffer::Iterator (this, GetSize ());
}
Buffer::Iterator::Iterator ()
: m_zeroStart (0),
m_zeroEnd (0),
m_dataEnd (0),
m_current (0),
m_data (0)
{}
Buffer::Iterator::Iterator (Buffer const*buffer, uint32_t current)
: m_zeroStart (buffer->m_data->m_initialStart-buffer->m_start),
m_zeroEnd (m_zeroStart+buffer->m_zeroAreaSize),
m_dataEnd (buffer->GetSize ()),
m_current (current),
m_data (buffer->m_data->m_data+buffer->m_start)
{}
void
Buffer::Iterator::Next (void)
{
NS_ASSERT (m_current + 1 <= m_dataEnd);
m_current++;
}
void
Buffer::Iterator::Prev (void)
{
NS_ASSERT (m_current >= 1);
m_current--;
}
void
Buffer::Iterator::Next (uint32_t delta)
{
NS_ASSERT (m_current + delta <= m_dataEnd);
m_current += delta;
}
void
Buffer::Iterator::Prev (uint32_t delta)
{
NS_ASSERT (m_current >= delta);
m_current -= delta;
}
int32_t
Buffer::Iterator::GetDistanceFrom (Iterator const &o) const
{
NS_ASSERT (m_data == o.m_data);
int32_t start = m_current;
int32_t end = o.m_current;
return end - start;
}
bool
Buffer::Iterator::IsEnd (void) const
{
return m_current == m_dataEnd;
}
bool
Buffer::Iterator::IsStart (void) const
{
return m_current == 0;
}
uint32_t
Buffer::Iterator::GetIndex (uint32_t n)
{
NS_ASSERT (
(m_current + n <= m_dataEnd) &&
((m_current + n <= m_zeroStart) ||
(m_current >= m_zeroEnd) ||
m_zeroStart == m_zeroEnd)
);
uint32_t index;
if (m_current < m_zeroStart)
{
index = m_current;
}
else
{
index = m_current - (m_zeroEnd-m_zeroStart);
}
return index;
}
void
Buffer::Iterator::Write (Iterator start, Iterator end)
{
NS_ASSERT (start.m_data == end.m_data);
NS_ASSERT (start.m_current <= end.m_current);
NS_ASSERT (start.m_zeroStart == end.m_zeroStart);
NS_ASSERT (start.m_zeroEnd == end.m_zeroEnd);
NS_ASSERT (m_data != start.m_data);
uint32_t size = end.m_current - start.m_current;
uint8_t *src = start.m_data + start.GetIndex (size);
uint8_t *dest = m_data + GetIndex (size);
memcpy (dest, src, size);
m_current += size;
}
void
Buffer::Iterator::WriteU8 (uint8_t data, uint32_t len)
{
uint8_t *current = m_data + GetIndex (len);
memset (current, data, len);
m_current += len;
}
void
Buffer::Iterator::WriteU8 (uint8_t data)
{
m_data[GetIndex (1)] = data;
m_current++;
}
void
Buffer::Iterator::WriteU16 (uint16_t data)
{
uint16_t *buffer = (uint16_t *)(m_data + GetIndex (2));
*buffer = data;
m_current += 2;
}
void
Buffer::Iterator::WriteU32 (uint32_t data)
{
uint32_t *buffer = (uint32_t *)(m_data + GetIndex (4));
*buffer = data;
m_current += 4;
}
void
Buffer::Iterator::WriteU64 (uint64_t data)
{
uint64_t *buffer = (uint64_t *)(m_data + GetIndex (8));
*buffer = data;
m_current += 8;
}
void
Buffer::Iterator::WriteHtonU16 (uint16_t data)
{
uint8_t *current = m_data + GetIndex (2);
*(current+0) = (data >> 8) & 0xff;
*(current+1) = (data >> 0) & 0xff;
m_current += 2;
}
void
Buffer::Iterator::WriteHtonU32 (uint32_t data)
{
uint8_t *current = m_data + GetIndex (4);
*(current+0) = (data >> 24) & 0xff;
*(current+1) = (data >> 16) & 0xff;
*(current+2) = (data >> 8) & 0xff;
*(current+3) = (data >> 0) & 0xff;
m_current += 4;
}
void
Buffer::Iterator::WriteHtonU64 (uint64_t data)
{
uint8_t *current = m_data + GetIndex (8);
*(current+0) = (data >> 56) & 0xff;
*(current+1) = (data >> 48) & 0xff;
*(current+2) = (data >> 40) & 0xff;
*(current+3) = (data >> 32) & 0xff;
*(current+4) = (data >> 24) & 0xff;
*(current+5) = (data >> 16) & 0xff;
*(current+6) = (data >> 8) & 0xff;
*(current+7) = (data >> 0) & 0xff;
m_current += 8;
}
void
Buffer::Iterator::Write (uint8_t const*buffer, uint16_t size)
{
uint8_t *current = m_data + GetIndex (size);
memcpy (current, buffer, size);
m_current += size;
}
uint8_t
Buffer::Iterator::ReadU8 (void)
{
uint8_t data = m_data[GetIndex(1)];
m_current++;
return data;
}
uint16_t
Buffer::Iterator::ReadU16 (void)
{
uint16_t *buffer = reinterpret_cast<uint16_t *>(m_data + GetIndex (2));
m_current += 2;
return *buffer;
}
uint32_t
Buffer::Iterator::ReadU32 (void)
{
uint32_t *buffer = reinterpret_cast<uint32_t *>(m_data + GetIndex (4));
m_current += 4;
return *buffer;
}
uint64_t
Buffer::Iterator::ReadU64 (void)
{
uint64_t *buffer = reinterpret_cast<uint64_t *>(m_data + GetIndex (8));
m_current += 8;
return *buffer;
}
uint16_t
Buffer::Iterator::ReadNtohU16 (void)
{
uint8_t *current = m_data + GetIndex (2);
uint16_t retval = 0;
retval |= static_cast<uint16_t> (current[0]) << 8;
retval |= static_cast<uint16_t> (current[1]) << 0;
m_current += 2;
return retval;
}
uint32_t
Buffer::Iterator::ReadNtohU32 (void)
{
uint8_t *current = m_data + GetIndex (4);
uint32_t retval = 0;
retval |= static_cast<uint32_t> (current[0]) << 24;
retval |= static_cast<uint32_t> (current[1]) << 16;
retval |= static_cast<uint32_t> (current[2]) << 8;
retval |= static_cast<uint32_t> (current[3]) << 0;
m_current += 4;
return retval;
}
uint64_t
Buffer::Iterator::ReadNtohU64 (void)
{
uint8_t *current = m_data + GetIndex (8);
uint64_t retval = 0;
retval |= static_cast<uint64_t> (current[0]) << 56;
retval |= static_cast<uint64_t> (current[1]) << 48;
retval |= static_cast<uint64_t> (current[2]) << 40;
retval |= static_cast<uint64_t> (current[3]) << 32;
retval |= static_cast<uint64_t> (current[4]) << 24;
retval |= static_cast<uint64_t> (current[5]) << 16;
retval |= static_cast<uint64_t> (current[6]) << 8;
retval |= static_cast<uint64_t> (current[7]) << 0;
m_current += 8;
return retval;
}
void
Buffer::Iterator::Read (uint8_t *buffer, uint16_t size)
{
uint8_t *current = m_data + GetIndex (size);
memcpy (buffer, current, size);
m_current += size;
}
}; // namespace ns3
#endif /* BUFFER_H */
+95
View File
@@ -0,0 +1,95 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "callback-trace-source.h"
#include "ns3/test.h"
namespace ns3 {
class CallbackTraceSourceTest : public Test
{
public:
CallbackTraceSourceTest ();
virtual ~CallbackTraceSourceTest ();
virtual bool RunTests (void);
private:
void CbOne (TraceContext const &context, uint8_t a, double b);
void CbTwo (TraceContext const &context, uint8_t a, double b);
bool m_one;
bool m_two;
};
CallbackTraceSourceTest::CallbackTraceSourceTest ()
: Test ("CallbackTraceSource")
{}
CallbackTraceSourceTest::~CallbackTraceSourceTest ()
{}
void
CallbackTraceSourceTest::CbOne (TraceContext const &context, uint8_t a, double b)
{
m_one = true;
}
void
CallbackTraceSourceTest::CbTwo (TraceContext const &context, uint8_t a, double b)
{
m_two = true;
}
bool
CallbackTraceSourceTest::RunTests (void)
{
bool ok = true;
TraceContext ctx;
CallbackTraceSource<uint8_t,double> trace;
trace.AddCallback (MakeCallback (&CallbackTraceSourceTest::CbOne, this), ctx);
trace.AddCallback (MakeCallback (&CallbackTraceSourceTest::CbTwo, this), ctx);
m_one = false;
m_two = false;
trace (1, 2);
if (!m_one || !m_two)
{
ok = false;
}
trace.RemoveCallback (MakeCallback (&CallbackTraceSourceTest::CbOne, this));
m_one = false;
m_two = false;
trace (1, 2);
if (m_one || !m_two)
{
ok = false;
}
trace.RemoveCallback (MakeCallback (&CallbackTraceSourceTest::CbTwo, this));
m_one = false;
m_two = false;
trace (1, 2);
if (m_one || m_two)
{
ok = false;
}
return ok;
}
CallbackTraceSourceTest g_callbackTraceTest;
}//namespace ns3
+157
View File
@@ -0,0 +1,157 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2005,2006,2007 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef CALLBACK_TRACE_H
#define CALLBACK_TRACE_H
#include <list>
#include "ns3/callback.h"
#include "ns3/fatal-error.h"
#include "trace-context.h"
namespace ns3 {
/**
* \brief log arbitrary number of parameters to a matching ns3::Callback
* \ingroup lowleveltracing
*
* Whenever operator () is invoked on this class, the call and its arguments
* are forwarded to the internal matching ns3::Callback.
*/
template<typename T1 = empty, typename T2 = empty,
typename T3 = empty, typename T4 = empty>
class CallbackTraceSource {
public:
CallbackTraceSource ();
void AddCallback (CallbackBase const & callback, TraceContext const & context);
void RemoveCallback (CallbackBase const & callback);
void operator() (void);
void operator() (T1 a1);
void operator() (T1 a1, T2 a2);
void operator() (T1 a1, T2 a2, T3 a3);
void operator() (T1 a1, T2 a2, T3 a3, T4 a4);
private:
typedef std::list<Callback<void,TraceContext const &,T1,T2,T3,T4> > CallbackList;
TraceContext m_context;
CallbackList m_callbackList;
};
}; // namespace ns3
// implementation below.
namespace ns3 {
template<typename T1, typename T2,
typename T3, typename T4>
CallbackTraceSource<T1,T2,T3,T4>::CallbackTraceSource ()
: m_callbackList ()
{}
template<typename T1, typename T2,
typename T3, typename T4>
void
CallbackTraceSource<T1,T2,T3,T4>::AddCallback (CallbackBase const & callback,
TraceContext const &context)
{
Callback<void,TraceContext const &,T1,T2,T3,T4> cb;
cb.Assign (callback);
m_context.Add (context);
m_callbackList.push_back (cb);
}
template<typename T1, typename T2,
typename T3, typename T4>
void
CallbackTraceSource<T1,T2,T3,T4>::RemoveCallback (CallbackBase const & callback)
{
for (typename CallbackList::iterator i = m_callbackList.begin ();
i != m_callbackList.end (); /* empty */)
{
if ((*i).IsEqual (callback))
{
i = m_callbackList.erase (i);
}
else
{
i++;
}
}
}
template<typename T1, typename T2,
typename T3, typename T4>
void
CallbackTraceSource<T1,T2,T3,T4>::operator() (void)
{
for (typename CallbackList::iterator i = m_callbackList.begin ();
i != m_callbackList.end (); i++)
{
(*i) (m_context);
}
}
template<typename T1, typename T2,
typename T3, typename T4>
void
CallbackTraceSource<T1,T2,T3,T4>::operator() (T1 a1)
{
for (typename CallbackList::iterator i = m_callbackList.begin ();
i != m_callbackList.end (); i++)
{
(*i) (m_context, a1);
}
}
template<typename T1, typename T2,
typename T3, typename T4>
void
CallbackTraceSource<T1,T2,T3,T4>::operator() (T1 a1, T2 a2)
{
for (typename CallbackList::iterator i = m_callbackList.begin ();
i != m_callbackList.end (); i++)
{
(*i) (m_context, a1, a2);
}
}
template<typename T1, typename T2,
typename T3, typename T4>
void
CallbackTraceSource<T1,T2,T3,T4>::operator() (T1 a1, T2 a2, T3 a3)
{
for (typename CallbackList::iterator i = m_callbackList.begin ();
i != m_callbackList.end (); i++)
{
(*i) (m_context, a1, a2, a3);
}
}
template<typename T1, typename T2,
typename T3, typename T4>
void
CallbackTraceSource<T1,T2,T3,T4>::operator() (T1 a1, T2 a2, T3 a3, T4 a4)
{
for (typename CallbackList::iterator i = m_callbackList.begin ();
i != m_callbackList.end (); i++)
{
(*i) (m_context, a1, a2, a3, a4);
}
}
}//namespace ns3
#endif /* CALLBACK_TRACE_H */
+65
View File
@@ -0,0 +1,65 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2005 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "chunk.h"
#include "ns3/assert.h"
namespace ns3 {
Chunk::Chunk ()
{}
Chunk::~Chunk ()
{}
std::string
Chunk::GetName (void) const
{
return DoGetName ();
}
void
Chunk::Print (std::ostream &os) const
{
PrintTo (os);
}
uint32_t
Chunk::GetSize (void) const
{
return GetSerializedSize ();
}
void
Chunk::Serialize (Buffer::Iterator start) const
{
SerializeTo (start);
}
uint32_t
Chunk::Deserialize (Buffer::Iterator start)
{
uint32_t deserialized = DeserializeFrom (start);
return deserialized;
}
std::ostream& operator<< (std::ostream& os, Chunk const& chunk)
{
chunk.Print (os);
return os;
}
}; // namespace ns3
+53
View File
@@ -0,0 +1,53 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2005 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef CHUNK_H
#define CHUNK_H
#include <stdint.h>
#include <ostream>
#include "buffer.h"
namespace ns3 {
class Chunk {
public:
Chunk ();
virtual ~Chunk ();
std::string GetName (void) const;
void Print (std::ostream &os) const;
uint32_t GetSize (void) const;
void Serialize (Buffer::Iterator start) const;
uint32_t Deserialize (Buffer::Iterator start);
private:
virtual std::string DoGetName (void) const = 0;
virtual void PrintTo (std::ostream &os) const = 0;
virtual uint32_t GetSerializedSize (void) const = 0;
virtual void SerializeTo (Buffer::Iterator i) const = 0;
virtual uint32_t DeserializeFrom (Buffer::Iterator i) = 0;
};
std::ostream& operator<< (std::ostream& os, Chunk const& chunk);
}; // namespace ns3
#endif /* CHUNK_H */
+331
View File
@@ -0,0 +1,331 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "composite-trace-resolver.h"
namespace ns3 {
CompositeTraceResolver::CompositeTraceResolver (TraceContext const &context)
: TraceResolver (context)
{}
CompositeTraceResolver::~CompositeTraceResolver ()
{}
void
CompositeTraceResolver::DoAdd (std::string name,
Callback<TraceResolver *,TraceContext const &> createResolver,
TraceContext const &context)
{
struct CallbackTraceSourceItem item;
item.name = name;
item.createResolver = createResolver;
item.context = context;
m_items.push_back (item);
}
TraceResolver::TraceResolverList
CompositeTraceResolver::DoLookup (std::string id) const
{
if (id == "*")
{
TraceResolver::TraceResolverList list;
for (TraceItems::const_iterator i = m_items.begin (); i != m_items.end (); i++)
{
list.push_back (i->createResolver (i->context));
}
return list;
}
std::string::size_type start, end;
start = id.find_first_of ("(", 0);
end = id.find_first_of (")", 0);
if (start != 0 || end != (id.size ()-1))
{
for (TraceItems::const_iterator i = m_items.begin (); i != m_items.end (); i++)
{
if (i->name == id)
{
TraceResolver::TraceResolverList list;
list.push_back (i->createResolver (i->context));
return list;
}
}
}
std::list<std::string> names;
std::string alternatives = std::string (id, start+1, end-1);
std::string::size_type next, cur;
next = 0;
cur = 0;
while (true)
{
std::string element;
next = alternatives.find ("|", cur);
if (next == std::string::npos)
{
element = std::string (alternatives, cur, alternatives.size ());
names.push_back (element);
break;
}
element = std::string (alternatives, cur, next);
names.push_back (element);
cur = next + 1;
}
TraceResolver::TraceResolverList list;
for (std::list<std::string>::const_iterator i = names.begin (); i != names.end (); i++)
{
for (TraceItems::const_iterator j = m_items.begin (); j != m_items.end (); j++)
{
if (j->name == *i)
{
list.push_back (j->createResolver (j->context));
break;
}
}
}
return list;
}
}//namespace ns3
#ifdef RUN_SELF_TESTS
#include "ns3/test.h"
namespace ns3 {
class CompositeTraceResolverTest : public Test
{
public:
enum TraceSources {
TEST_TRACE_DOUBLEA,
TEST_TRACE_DOUBLEB,
TEST_TRACE_SUBRESOLVER,
};
enum SubTraceSources {
TEST_SUBTRACE_INT,
};
CompositeTraceResolverTest ();
virtual ~CompositeTraceResolverTest ();
virtual bool RunTests (void);
private:
void TraceDouble (TraceContext const &context, double v);
void TraceInt (TraceContext const &context, int v);
TraceResolver *CreateSubResolver (TraceContext const &context);
bool m_gotDoubleA;
bool m_gotDoubleB;
CallbackTraceSource<int> m_traceInt;
bool m_gotInt;
};
CompositeTraceResolverTest::CompositeTraceResolverTest ()
: Test ("CompositeTraceResolver")
{}
CompositeTraceResolverTest::~CompositeTraceResolverTest ()
{}
void
CompositeTraceResolverTest::TraceDouble (TraceContext const &context, double v)
{
enum CompositeTraceResolverTest::TraceSources source;
context.Get (source);
switch (source)
{
case TEST_TRACE_DOUBLEA:
m_gotDoubleA = true;
break;
case TEST_TRACE_DOUBLEB:
m_gotDoubleB = true;
break;
default:
NS_FATAL_ERROR ("should not get any other trace source in this sink");
break;
}
}
void
CompositeTraceResolverTest::TraceInt (TraceContext const &context, int v)
{
m_gotInt = true;
}
TraceResolver *
CompositeTraceResolverTest::CreateSubResolver (TraceContext const &context)
{
CompositeTraceResolver *subresolver = new CompositeTraceResolver (context);
subresolver->Add ("trace-int", m_traceInt, TEST_SUBTRACE_INT);
return subresolver;
}
bool
CompositeTraceResolverTest::RunTests (void)
{
bool ok = true;
CallbackTraceSource<double> traceDoubleA;
CallbackTraceSource<double> traceDoubleB;
TraceContext context;
CompositeTraceResolver resolver (context) ;
resolver.Add ("trace-double-a", traceDoubleA, TEST_TRACE_DOUBLEA);
resolver.Add ("trace-double-b", traceDoubleB, TEST_TRACE_DOUBLEB);
resolver.Connect ("/*", MakeCallback (&CompositeTraceResolverTest::TraceDouble, this));
m_gotDoubleA = false;
m_gotDoubleB = false;
traceDoubleA (0);
if (!m_gotDoubleA || m_gotDoubleB)
{
ok = false;
}
m_gotDoubleA = false;
traceDoubleA (0);
traceDoubleB (0);
if (!m_gotDoubleA || !m_gotDoubleB)
{
ok = false;
}
m_gotDoubleA = false;
m_gotDoubleB = false;
resolver.Disconnect ("/*", MakeCallback (&CompositeTraceResolverTest::TraceDouble, this));
m_gotDoubleA = false;
m_gotDoubleB = false;
traceDoubleA (0);
traceDoubleB (0);
if (m_gotDoubleA || m_gotDoubleB)
{
ok = false;
}
resolver.Connect ("/trace-double-a",
MakeCallback (&CompositeTraceResolverTest::TraceDouble, this));
m_gotDoubleA = false;
m_gotDoubleB = false;
traceDoubleA (0);
traceDoubleB (0);
if (!m_gotDoubleA || m_gotDoubleB)
{
ok = false;
}
resolver.Disconnect ("/trace-double-a",
MakeCallback (&CompositeTraceResolverTest::TraceDouble, this));
resolver.Connect ("/(trace-double-a)",
MakeCallback (&CompositeTraceResolverTest::TraceDouble, this));
m_gotDoubleA = false;
m_gotDoubleB = false;
traceDoubleA (0);
traceDoubleB (0);
if (!m_gotDoubleA || m_gotDoubleB)
{
ok = false;
}
resolver.Disconnect ("/trace-double-a",
MakeCallback (&CompositeTraceResolverTest::TraceDouble, this));
resolver.Connect ("/(trace-double-a|trace-double-b)",
MakeCallback (&CompositeTraceResolverTest::TraceDouble, this));
m_gotDoubleA = false;
m_gotDoubleB = false;
traceDoubleA (0);
traceDoubleB (0);
if (!m_gotDoubleA || !m_gotDoubleB)
{
ok = false;
}
resolver.Disconnect ("/trace-double-a",
MakeCallback (&CompositeTraceResolverTest::TraceDouble, this));
m_gotDoubleA = false;
m_gotDoubleB = false;
traceDoubleA (0);
traceDoubleB (0);
if (m_gotDoubleA || !m_gotDoubleB)
{
ok = false;
}
resolver.Disconnect ("/(trace-double-a|trace-double-b)",
MakeCallback (&CompositeTraceResolverTest::TraceDouble, this));
m_gotDoubleA = false;
m_gotDoubleB = false;
traceDoubleA (0);
traceDoubleB (0);
if (m_gotDoubleA || m_gotDoubleB)
{
ok = false;
}
resolver.Add ("subresolver",
MakeCallback (&CompositeTraceResolverTest::CreateSubResolver, this),
TEST_TRACE_SUBRESOLVER);
resolver.Connect ("/subresolver/trace-int",
MakeCallback (&CompositeTraceResolverTest::TraceInt, this));
m_gotInt = false;
m_traceInt (1);
if (!m_gotInt)
{
ok = false;
}
resolver.Disconnect ("/subresolver/trace-int",
MakeCallback (&CompositeTraceResolverTest::TraceInt, this));
m_gotInt = false;
m_traceInt (1);
if (m_gotInt)
{
ok = false;
}
resolver.Connect ("/*/trace-int",
MakeCallback (&CompositeTraceResolverTest::TraceInt, this));
m_gotInt = false;
m_traceInt (1);
if (!m_gotInt)
{
ok = false;
}
resolver.Disconnect ("/subresolver/trace-int",
MakeCallback (&CompositeTraceResolverTest::TraceInt, this));
m_gotInt = false;
m_traceInt (1);
if (m_gotInt)
{
ok = false;
}
return ok;
}
static CompositeTraceResolverTest g_compositeTraceResolverTest;
}//namespace ns3
#endif /* RUN_SELF_TESTS */
+211
View File
@@ -0,0 +1,211 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef COMPOSITE_TRACE_RESOLVER_H
#define COMPOSITE_TRACE_RESOLVER_H
#include "ns3/callback.h"
#include "trace-resolver.h"
#include "callback-trace-source.h"
#include "uv-trace-source.h"
#include "sv-trace-source.h"
#include "fv-trace-source.h"
#include "terminal-trace-resolver.h"
namespace ns3 {
/**
* \brief a helper class to aggregate contained TraceResolver and other trace sources.
* \ingroup lowleveltracing
*/
class CompositeTraceResolver : public TraceResolver
{
public:
CompositeTraceResolver (TraceContext const &context);
virtual ~CompositeTraceResolver ();
/**
* \param name name of trace source
* \param trace a callback trace source
* \param context the context associated to this trace source
*
* Add a callback trace source in this resolver. This trace
* source will match the name specified during namespace
* resolution. The TraceContext of this trace source will also
* be automatically extended to contain the input context.
*/
template <typename T1, typename T2,
typename T3, typename T4,
typename T>
void Add (std::string name,
CallbackTraceSource<T1,T2,T3,T4> &trace, T const &context);
/**
* \param name name of trace source
* \param trace a signed variable trace source
* \param context the context associated to this trace source
*
* Add a signed variable trace source in this resolver.
* This trace source will match the name specified during namespace
* resolution. The TraceContext of this trace source will also
* be automatically extended to contain the input context.
*/
template <typename T>
void Add (std::string name,
SVTraceSource<T> &trace, T const &context);
/**
* \param name name of trace source
* \param trace an unsigned variable trace source
* \param context the context associated to this trace source
*
* Add an unsigned variable trace source in this resolver.
* This trace source will match the name specified during namespace
* resolution. The TraceContext of this trace source will also
* be automatically extended to contain the input context.
*/
template <typename T>
void Add (std::string name,
UVTraceSource<T> &trace, T const &context);
/**
* \param name name of trace source
* \param trace a floating-point variable trace source
* \param context the context associated to this trace source
*
* Add a floating-point variable trace source in this resolver.
* This trace source will match the name specified during namespace
* resolution. The TraceContext of this trace source will also
* be automatically extended to contain the input context.
*/
template <typename T>
void Add (std::string name,
FVTraceSource<T> &trace, T const &context);
/**
* \param name name of child trace resolver
* \param createResolver a trace resolver constructor
* \param context the context associated to this entry
*
* Add a child trace resolver to this resolver. This child
* trace resolver will match the name specified during
* namespace resolution. When this happens, the constructor
* will be invoked to create the child trace resolver and
* the associated TraceContext will be automatically extended
* to contain the input context.
*/
template <typename T>
void Add (std::string name,
Callback<TraceResolver *,TraceContext const &> createResolver,
T const &context);
private:
template <typename SOURCE, typename CONTEXT>
void DoAddTraceSource (std::string name,
SOURCE &traceSource, CONTEXT const &context);
template <typename SOURCE>
static TraceResolver *CreateTerminalTraceResolver (SOURCE *trace,
TraceContext const &context);
void DoAdd (std::string name,
Callback<TraceResolver *,TraceContext const &> createResolver,
TraceContext const &context);
virtual TraceResolverList DoLookup (std::string id) const;
struct CallbackTraceSourceItem
{
std::string name;
Callback<TraceResolver *,TraceContext const &> createResolver;
TraceContext context;
};
typedef std::list<struct CallbackTraceSourceItem> TraceItems;
TraceItems m_items;
};
}//namespace ns3
namespace ns3 {
template <typename SOURCE, typename CONTEXT>
void
CompositeTraceResolver::DoAddTraceSource (std::string name,
SOURCE &traceSource, CONTEXT const &context)
{
TraceContext traceContext = GetContext ();
traceContext.Add (context);
TraceResolver *(*create) (SOURCE *trace, TraceContext const &context);
create = &CompositeTraceResolver::CreateTerminalTraceResolver<SOURCE>;
Callback<TraceResolver *,TraceContext const &> createResolver =
MakeBoundCallback (create, &traceSource);
DoAdd (name, createResolver, traceContext);
}
template <typename SOURCE>
TraceResolver *
CompositeTraceResolver::CreateTerminalTraceResolver (SOURCE *traceSource,
TraceContext const &context)
{
return new TerminalTraceResolver<SOURCE> (*traceSource, context);
}
template <typename T1, typename T2,
typename T3, typename T4,
typename T>
void
CompositeTraceResolver::Add (std::string name,
CallbackTraceSource<T1,T2,T3,T4> &trace,
T const &context)
{
DoAddTraceSource (name, trace, context);
}
template <typename T>
void
CompositeTraceResolver::Add (std::string name,
SVTraceSource<T> &trace, T const &context)
{
DoAddTraceSource (name, trace, context);
}
template <typename T>
void
CompositeTraceResolver::Add (std::string name,
UVTraceSource<T> &trace, T const &context)
{
DoAddTraceSource (name, trace, context);
}
template <typename T>
void
CompositeTraceResolver::Add (std::string name,
FVTraceSource<T> &trace, T const &context)
{
DoAddTraceSource (name, trace, context);
}
template <typename T>
void
CompositeTraceResolver::Add (std::string name,
Callback<TraceResolver *,TraceContext const &> createResolver,
T const &context)
{
TraceContext traceContext = GetContext ();
traceContext.Add (context);
DoAdd (name, createResolver, traceContext);
}
}//namespace ns3
#endif /* COMPOSITE_TRACE_RESOLVER_H */
+255
View File
@@ -0,0 +1,255 @@
/* -*- 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: Rajib Bhattacharjea<raj.b@gatech.edu>
//
#include "data-rate.h"
#include "ns3/nstime.h"
#include "ns3/fatal-error.h"
static bool
DoParse (const std::string s, uint64_t *v)
{
std::string::size_type n = s.find_first_not_of("0123456789.");
if (n != std::string::npos)
{ // Found non-numeric
double r = ::atof(s.substr(0, n).c_str());
std::string trailer = s.substr(n, std::string::npos);
if (trailer == "bps")
{
// Bit/s
*v = (uint64_t)r;
}
else if (trailer == "b/s")
{
// Bit/s
*v = (uint64_t)r;
}
else if (trailer == "Bps")
{
// Byte/s
*v = (uint64_t)(r * 8);
}
else if (trailer == "B/s")
{
// Byte/s
*v = (uint64_t)(r * 8);
}
else if (trailer == "kbps")
{
// KiloBit/s
*v = (uint64_t)(r * 1000);
}
else if (trailer == "kb/s")
{
// KiloBit/s
*v = (uint64_t)(r * 1000);
}
else if (trailer == "kBps")
{
// KiloBit/s
*v = (uint64_t)(r * 1000);
}
else if (trailer == "kB/s")
{
// KiloBit/s
*v = (uint64_t)(r * 1000);
}
else if (trailer == "Mbps")
{
// MegaBit/s
*v = (uint64_t)(r * 1000000);
}
else if (trailer == "Mb/s")
{
// MegaBit/s
*v = (uint64_t)(r * 1000000);
}
else if (trailer == "MBps")
{
// MegaByte/s
*v = (uint64_t)(r * 8000000);
}
else if (trailer == "MB/s")
{
// MegaByte/s
*v = (uint64_t)(r * 8000000);
}
else if (trailer == "Gbps")
{
// GigaBit/s
*v = (uint64_t)(r * 1000000000);
}
else if (trailer == "Gb/s")
{
// GigaBit/s
*v = (uint64_t)(r * 1000000000);
}
else if (trailer == "GBps")
{
// GigaByte/s
*v = (uint64_t)(r * 8*1000000000);
}
else if (trailer == "GB/s")
{
// GigaByte/s
*v = (uint64_t)(r * 8*1000000000);
}
else
{
return false;
}
return true;
}
*v = ::atoll(s.c_str());
return true;
}
namespace ns3 {
DataRate::DataRate(uint64_t bps)
:m_bps(bps)
{
}
DataRate::DataRate (const std::string s)
: m_bps(DataRate::Parse(s))
{
}
uint64_t DataRate::Parse(const std::string s)
{
uint64_t v;
if (!DoParse (s, &v))
{
NS_FATAL_ERROR("Can't Parse data rate "<<s);
}
return v;
}
bool DataRate::operator < (const DataRate& rhs)
{
return m_bps<rhs.m_bps;
}
bool DataRate::operator <= (const DataRate& rhs)
{
return m_bps<=rhs.m_bps;
}
bool DataRate::operator > (const DataRate& rhs)
{
return m_bps>rhs.m_bps;
}
bool DataRate::operator >= (const DataRate& rhs)
{
return m_bps>=rhs.m_bps;
}
bool DataRate::operator == (const DataRate& rhs)
{
return m_bps==rhs.m_bps;
}
bool DataRate::operator != (const DataRate& rhs)
{
return m_bps!=rhs.m_bps;
}
double DataRate::CalculateTxTime(uint32_t bytes) const
{
return static_cast<double>(bytes)*8/m_bps;
}
uint64_t DataRate::GetBitRate() const
{
return m_bps;
}
double operator*(const DataRate& lhs, const Time& rhs)
{
return rhs.GetSeconds()*lhs.GetBitRate();
}
double operator*(const Time& lhs, const DataRate& rhs)
{
return lhs.GetSeconds()*rhs.GetBitRate();
}
DataRateDefaultValue::DataRateDefaultValue (std::string name,
std::string help,
DataRate defaultValue)
: DefaultValueBase (name, help),
m_defaultValue (defaultValue),
m_value (defaultValue)
{
DefaultValueList::Add (this);
}
void
DataRateDefaultValue::SetValue (DataRate rate)
{
m_value = rate;
}
DataRate
DataRateDefaultValue::GetValue ()
{
return m_value;
}
bool
DataRateDefaultValue::DoParseValue (const std::string &value)
{
uint64_t v;
if (DoParse (value, &v))
{
m_value = DataRate (v);
return true;
}
return false;
}
std::string
DataRateDefaultValue::DoGetType (void) const
{
return "(b/s|kb/s|Mb/s)";
}
std::string
DataRateDefaultValue::DoGetDefaultValue (void) const
{
uint64_t defaultValue = m_defaultValue.GetBitRate ();
std::ostringstream oss;
if (defaultValue < 1000)
{
oss << defaultValue << "b/s";
}
else if (defaultValue < 1000000)
{
oss << (defaultValue/1000) << "kb/s";
}
else
{
oss << (defaultValue/1000) << "Mb/s";
}
return oss.str ();
}
};//namespace ns3
+127
View File
@@ -0,0 +1,127 @@
/* -*- 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: Rajib Bhattacharjea<raj.b@gatech.edu>
//
#ifndef DATA_RATE_H
#define DATA_RATE_H
#include <string>
#include <iostream>
#include <stdint.h>
#include "ns3/nstime.h"
#include "ns3/default-value.h"
namespace ns3 {
/**
* \brief Class for representing data rates
*
* Allows for natural and familiar use of data rates. Allows construction
* from strings, natural multiplication e.g.:
* \code
* DataRate x("56kbps");
* double nBits = x*ns3::Seconds(19.2);
* uint32_t nBytes = 20;
* double txtime = x.CalclulateTxTime(nBytes);
* \endcode
* This class also supports the regular comparison operators <, >, <=, >=, ==,
* and !=
*/
class DataRate
{
public:
/**
* \brief Integer constructor
*
* Construct a data rate from an integer. This class only supports positive
* integer data rates in units of bits/s, meaning 1bit/s is the smallest
* non-trivial bitrate availiable.
*/
DataRate (uint64_t bps);
/**
* \brief String constructor
*
* Construct a DataRate from a string. The supported strings have a
* numerical portion, followed by units in the following format:
* - Prefix: nothing, "k", "M", "G"
* - Data Unit: "b, "B"
* - Time Suffix: "ps", "/s" \n
* The prefixes are SI powers of 10 (10^0,10^3,10^6,10^9 respectively).\n
* The units are the bit, and the (8-bit) byte respectively.\n
* Both time suffixes denote "per second". Some supported examples include
* "20B/s", "56kbps", "4.4MB/s", and "100Gb/s". Any malformed string causes
* a fatal error.
*/
DataRate (const std::string s);
bool operator < (const DataRate& rhs);
bool operator <= (const DataRate& rhs);
bool operator > (const DataRate& rhs);
bool operator >= (const DataRate& rhs);
bool operator == (const DataRate& rhs);
bool operator != (const DataRate& rhs);
/**
* \brief Calculate transmission time
*
* Calculates the transmission time at this data rate
* \param bytes The number of bytes (not bits) for which to calculate
* \return The tranmission time in seconds for the number of bytes specified
*/
double CalculateTxTime(uint32_t bytes) const;
/**
* Get the underlying bitrate
* \return The underlying bitrate in bits per second
*/
uint64_t GetBitRate() const;
private:
uint64_t m_bps;
static uint64_t Parse(const std::string);
};
/**
* \param lhs
* \param rhs
* \return Bits transmitted in rhs seconds at lhs b/s
*/
double operator*(const DataRate& lhs, const TimeUnit<1>& rhs);
double operator*(const TimeUnit<1>& lhs, const DataRate& rhs);
class DataRateDefaultValue : public DefaultValueBase
{
public:
DataRateDefaultValue (std::string name,
std::string help,
DataRate defaultValue);
void SetValue (DataRate rate);
DataRate GetValue ();
private:
virtual bool DoParseValue (const std::string &value);
virtual std::string DoGetType (void) const;
virtual std::string DoGetDefaultValue (void) const;
DataRate m_defaultValue;
DataRate m_value;
};
};//namespace ns3
#endif /* DATA_RATE_H */
+121
View File
@@ -0,0 +1,121 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2005 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "data-writer.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/poll.h>
#include <fcntl.h>
#include <unistd.h>
#include "ns3/assert.h"
#include <string.h>
#include <list>
#define noTRACE_DATA_WRITER 1
#ifdef TRACE_DATA_WRITER
#include <iostream>
# define TRACE(x) \
std::cout << "DATA WRITER TRACE " << this << " " << x << std::endl;
#else /* TRACE_DATA_WRITER */
# define TRACE(format,...)
#endif /* TRACE_DATA_WRITER */
#define BUFFER_SIZE (4096)
namespace ns3 {
class DataWriterPrivate {
public:
DataWriterPrivate ();
~DataWriterPrivate ();
void open (char const *filename);
void write (uint8_t *buffer, uint32_t size);
private:
uint8_t m_data[BUFFER_SIZE];
uint32_t m_current;
int m_fd;
};
DataWriterPrivate::DataWriterPrivate ()
: m_current (0)
{}
DataWriterPrivate::~DataWriterPrivate ()
{
::Write (m_fd, m_data, m_current);
::Close (m_fd);
}
void
DataWriterPrivate::Open (char const *filename)
{
m_fd = ::Open (filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
NS_ASSERT (m_fd != -1);
}
#ifndef min
#define min(a,b) ((a)<(b)?(a):(b))
#endif /* min */
void
DataWriterPrivate::Write (uint8_t *buffer, uint32_t size)
{
while (size > 0)
{
uint32_t toCopy = min (BUFFER_SIZE - m_current, size);
memcpy (m_data + m_current, buffer, toCopy);
size -= toCopy;
m_current += toCopy;
buffer += toCopy;
if (m_current == BUFFER_SIZE)
{
ssize_t written = 0;
written = ::Write (m_fd, m_data, BUFFER_SIZE);
NS_ASSERT (written == BUFFER_SIZE);
m_current = 0;
}
}
}
DataWriter::DataWriter ()
: m_priv (new DataWriterPrivate ())
{}
DataWriter::~DataWriter ()
{
delete m_priv;
m_priv = 0;
}
void
DataWriter::Open (char const *filename)
{
m_priv->Open (filename);
}
void
DataWriter::Write (uint8_t *buffer, uint32_t size)
{
m_priv->Write (buffer, size);
}
}; // namespace
+44
View File
@@ -0,0 +1,44 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2005 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef DATA_WRITER_H
#define DATA_WRITER_H
#include <stdint.h>
namespace ns3 {
class DataWriterPrivate;
class DataWriter {
public:
DataWriter ();
~DataWriter ();
void open (char const *filename);
void write (uint8_t *buffer, uint32_t size);
private:
DataWriterPrivate *m_priv;
};
}; //namespace ns3
#endif /* DATA_WRITER_H */
+25
View File
@@ -0,0 +1,25 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "empty-trace-resolver.h"
ns3::EmptyTraceResolver::EmptyTraceResolver (TraceContext const &context)
: TraceResolver (context)
{}
+52
View File
@@ -0,0 +1,52 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef EMPTY_TRACE_RESOLVER_H
#define EMPTY_TRACE_RESOLVER_H
#include "trace-resolver.h"
namespace ns3 {
class TraceContext;
/**
* \brief a TraceResolver instance which does not resolve anything.
* \ingroup tracing
*
* Trying to resolve against this class will yield no matches and no
* connections. Returning an instance of this class from a
* CreateTraceResolver method is a hand way of not implementing
* any Tracing code.
*/
class EmptyTraceResolver : public TraceResolver
{
public:
/**
* \param o necessary context for this class.
*
* The only constructor exported by this class.
*/
EmptyTraceResolver (TraceContext const &o);
};
}//namespace ns3
#endif /* EMPTY_TRACE_RESOLVER_H */
+67
View File
@@ -0,0 +1,67 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2006 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef F_VARIABLE_TRACER_H
#define F_VARIABLE_TRACER_H
#include "callback-trace-source.h"
#include <stdint.h>
namespace ns3 {
class FVTraceSourceBase {
public:
typedef CallbackTraceSource<double, double> ChangeNotifyCallback;
FVTraceSourceBase () {}
FVTraceSourceBase (FVTraceSourceBase const &o) {}
FVTraceSourceBase &operator = (FVTraceSourceBase const &o) {
return *this;
}
~FVTraceSourceBase () {}
void AddCallback (CallbackBase const & callback, TraceContext const & context) {
m_callback.AddCallback (callback, context);
}
void RemoveCallback (CallbackBase const & callback) {
m_callback.RemoveCallback (callback);
}
protected:
void notify (double oldVal, double newVal) {
if (oldVal != newVal)
{
m_callback (oldVal, newVal);
}
}
private:
ChangeNotifyCallback m_callback;
};
template <typename T>
class FVTraceSource : public FVTraceSourceBase
{
public:
};
}; // namespace ns3
#endif /* F_VARIABLE_TRACER_H */
+29
View File
@@ -0,0 +1,29 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2005 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "header.h"
namespace ns3 {
Header::~Header ()
{}
}; // namespace ns3
+97
View File
@@ -0,0 +1,97 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2005 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef HEADER_H
#define HEADER_H
#include "chunk.h"
namespace ns3 {
/**
* \brief Protocol header serialization and deserialization.
*
* Every Protocol header which needs to be inserted or removed
* from a Packet instance must derive from this abstract base class
* and implement the private pure virtual methods listed below:
* - ns3::Header::SerializeTo
* - ns3::Header::DeserializeFrom
* - ns3::Header::GetSerializedSize
* - ns3::Header::PrintTo
*/
class Header : public Chunk {
public:
virtual ~Header ();
private:
/**
* \returns a user-readable name to identify this type of header.
*
* The string returned is expected to be a single word with
* all capital letters
*/
virtual std::string DoGetName (void) const = 0;
/**
* \param os the std output stream in which this
* protocol header must print itself.
*
* Although the header is free to format its output as it
* wishes, it is recommended to follow a few rules to integrate
* with the packet pretty printer:
* - start with flags, small field values located between a
* pair of parens. Values should be separated by whitespace.
* - follow the parens with the important fields, separated by
* whitespace.
* i.e.:
* (field1 val1 field2 val2 field3 val3) field4 val4 field5 val5
*/
virtual void PrintTo (std::ostream &os) const = 0;
/**
* \returns the size of the serialized Header.
*
* This method is used by Packet::AddHeader to reserve
* enough room in the packet byte buffer prior to calling
* Header::Serialize.
*/
virtual uint32_t GetSerializedSize (void) const = 0;
/**
* \param start the buffer iterator in which the protocol header
* must serialize itself. This iterator identifies
* the start of the buffer.
*/
virtual void SerializeTo (Buffer::Iterator start) const = 0;
/**
* \param start the buffer iterator from which the protocol header must
* deserialize itself. This iterator identifies
* the start of the buffer.
* \returns the number of bytes read from the buffer
*
* The value returned is used to trim the packet byte buffer of the
* corresponding amount when this method is invoked from
* Packet::RemoveHeader
*/
virtual uint32_t DeserializeFrom (Buffer::Iterator start) = 0;
};
}; // namespace ns3
#endif /* HEADER_H */
File diff suppressed because it is too large Load Diff
+335
View File
@@ -0,0 +1,335 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2006,2007 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef PACKET_METADATA_H
#define PACKET_METADATA_H
#include <stdint.h>
#include <vector>
#include "ns3/callback.h"
#include "ns3/assert.h"
#include "packet-printer.h"
namespace ns3 {
class Chunk;
class Buffer;
/**
* \internal
* \brief handle packet metadata about packet headers and trailers
*
* This class is used by the Packet class to record every operation
* performed on the packet's buffer. This class also provides
* an implementation of the Packet::Print methods which uses
* the metadata to analyse the content of the packet's buffer.
*
* To achieve this, this class maintains a linked list of so-called
* "items", each of which represents a header or a trailer, or
* payload, or a fragment of any of these. Each item contains a "next"
* and a "prev" field which point to the next and previous entries
* in the linked list. The PacketMetadata class maintains a pair
* of pointers to the head and the tail of the linked list.
*
* Each entry in the list also maintains:
* - its native size (the size it had when it was first added
* to the packet)
* - its type: identifies what kind of header, what kind of trailer,
* if it is payload or not
* - the uid of the packet to which it was first added
* - the start and end of the area represented by a fragment
* if it is one.
*
* This linked list is flattened in a byte buffer stored in
* struct PacketMetadata::Data. Each entry of the linked list is
* identified by an offset which identifies the first byte of the
* entry from the start of the data buffer. The size of this data
* buffer is 2^16-1 bytes maximum which somewhat limits the number
* of entries which can be stored in this linked list but it is
* quite unlikely to hit this limit in practice.
*
* Each item of the linked list is a variable-sized byte buffer
* made of a number of fields. Some of these fields are stored
* as fixed-size 32 bit integers, others as fixed-size 16 bit
* integers, and some others as variable-size 32-bit integers.
* The variable-size 32 bit integers are stored using the uleb128
* encoding.
*/
class PacketMetadata {
public:
static void Enable (void);
static void SetOptOne (bool optOne);
inline PacketMetadata (uint32_t uid, uint32_t size);
inline PacketMetadata (PacketMetadata const &o);
inline PacketMetadata &operator = (PacketMetadata const& o);
inline ~PacketMetadata ();
template <typename T>
void AddHeader (T const &header, uint32_t size);
template <typename T>
void RemoveHeader (T const &header, uint32_t size);
template <typename T>
void AddTrailer (T const &trailer, uint32_t size);
template <typename T>
void RemoveTrailer (T const &trailer, uint32_t size);
PacketMetadata CreateFragment (uint32_t start, uint32_t end) const;
void AddAtEnd (PacketMetadata const&o);
void AddPaddingAtEnd (uint32_t end);
void RemoveAtStart (uint32_t start);
void RemoveAtEnd (uint32_t end);
uint32_t GetUid (void) const;
void PrintDefault (std::ostream &os, Buffer buffer) const;
void Print (std::ostream &os, Buffer buffer, PacketPrinter const &printer) const;
static void PrintStats (void);
private:
struct Data {
/* number of references to this struct Data instance. */
uint16_t m_count;
/* size (in bytes) of m_data buffer below */
uint16_t m_size;
/* max of the m_used field over all objects which
* reference this struct Data instance */
uint16_t m_dirtyEnd;
/* variable-sized buffer of bytes */
uint8_t m_data[10];
};
/* Note that since the next and prev fields are 16 bit integers
and since the value 0xffff is reserved to identify the
fact that the end or the start of the list is reached,
only a limited number of elements can be stored in
a m_data byte buffer.
*/
struct SmallItem {
/* offset (in bytes) from start of m_data buffer
to next element in linked list. value is 0xffff
if next element does not exist.
stored as a fixed-size 16 bit integer.
*/
uint16_t next;
/* offset (in bytes) from start of m_data buffer
to previous element in linked list. value is 0xffff
if previous element does not exist.
stored as a fixed-size 16 bit integer.
*/
uint16_t prev;
/* the high 31 bits of this field identify the
type of the header or trailer represented by
this item: the value zero represents payload.
If the low bit of this uid is one, an ExtraItem
structure follows this SmallItem structure.
stored as a variable-size 32 bit integer.
*/
uint32_t typeUid;
/* the size (in bytes) of the header or trailer represented
by this element.
stored as a variable-size 32 bit integer.
*/
uint32_t size;
/* this field tries to uniquely identify each header or
trailer _instance_ while the typeUid field uniquely
identifies each header or trailer _type_. This field
is used to test whether two items are equal in the sense
that they represent the same header or trailer instance.
That equality test is based on the typeUid and chunkUid
fields so, the likelyhood that two header instances
share the same chunkUid _and_ typeUid is very small
unless they are really representations of the same header
instance.
stored as a fixed-size 16 bit integer.
*/
uint16_t chunkUid;
};
struct ExtraItem {
/* offset (in bytes) from start of original header to
the start of the fragment still present.
stored as a variable-size 32 bit integer.
*/
uint32_t fragmentStart;
/* offset (in bytes) from start of original header to
the end of the fragment still present.
stored as a variable-size 32 bit integer.
*/
uint32_t fragmentEnd;
/* the packetUid of the packet in which this header or trailer
was first added. It could be different from the m_packetUid
field if the user has aggregated multiple packets into one.
stored as a fixed-size 32 bit integer.
*/
uint32_t packetUid;
};
typedef std::vector<struct Data *> DataFreeList;
PacketMetadata ();
void DoAddHeader (uint32_t uid, uint32_t size);
void DoRemoveHeader (uint32_t uid, uint32_t size);
void DoAddTrailer (uint32_t uid, uint32_t size);
void DoRemoveTrailer (uint32_t uid, uint32_t size);
inline uint16_t AddSmall (const PacketMetadata::SmallItem *item);
uint16_t AddBig (uint32_t head, uint32_t tail,
const PacketMetadata::SmallItem *item,
const PacketMetadata::ExtraItem *extraItem);
void ReplaceTail (PacketMetadata::SmallItem *item,
PacketMetadata::ExtraItem *extraItem,
uint32_t available);
inline void UpdateHead (uint16_t written);
inline void UpdateTail (uint16_t written);
uint32_t GetUleb128Size (uint32_t value) const;
uint32_t ReadUleb128 (const uint8_t **pBuffer) const;
inline void Append16 (uint16_t value, uint8_t *buffer);
inline bool TryToAppend (uint32_t value, uint8_t **pBuffer, uint8_t *end);
inline bool TryToAppendFast (uint32_t value, uint8_t **pBuffer, uint8_t *end);
inline bool TryToAppend32 (uint32_t value, uint8_t **pBuffer, uint8_t *end);
inline bool TryToAppend16 (uint16_t value, uint8_t **pBuffer, uint8_t *end);
void AppendValue (uint32_t value, uint8_t *buffer);
void AppendValueExtra (uint32_t value, uint8_t *buffer);
inline void Reserve (uint32_t n);
void ReserveCopy (uint32_t n);
uint32_t DoPrint (const struct PacketMetadata::SmallItem *item,
const struct PacketMetadata::ExtraItem *extraItem,
Buffer data, uint32_t offset, const PacketPrinter &printer,
std::ostream &os) const;
uint32_t GetTotalSize (void) const;
uint32_t ReadItems (uint16_t current,
struct PacketMetadata::SmallItem *item,
struct PacketMetadata::ExtraItem *extraItem) const;
static struct PacketMetadata::Data *Create (uint32_t size);
static void Recycle (struct PacketMetadata::Data *data);
static struct PacketMetadata::Data *Allocate (uint32_t n);
static void Deallocate (struct PacketMetadata::Data *data);
static DataFreeList m_freeList;
static bool m_enable;
static uint32_t m_maxSize;
static uint16_t m_chunkUid;
struct Data *m_data;
/**
head -(next)-> tail
^ |
\---(prev)---|
*/
uint16_t m_head;
uint16_t m_tail;
uint16_t m_used;
uint32_t m_packetUid;
};
}; // namespace ns3
namespace ns3 {
template <typename T>
void
PacketMetadata::AddHeader (T const &header, uint32_t size)
{
DoAddHeader (PacketPrinter::GetHeaderUid<T> (), size);
}
template <typename T>
void
PacketMetadata::RemoveHeader (T const &header, uint32_t size)
{
DoRemoveHeader (PacketPrinter::GetHeaderUid<T> (), size);
}
template <typename T>
void
PacketMetadata::AddTrailer (T const &trailer, uint32_t size)
{
DoAddTrailer (PacketPrinter::GetTrailerUid<T> (), size);
}
template <typename T>
void
PacketMetadata::RemoveTrailer (T const &trailer, uint32_t size)
{
DoRemoveTrailer (PacketPrinter::GetTrailerUid<T> (), size);
}
PacketMetadata::PacketMetadata (uint32_t uid, uint32_t size)
: m_data (m_data = PacketMetadata::Create (10)),
m_head (0xffff),
m_tail (0xffff),
m_used (0),
m_packetUid (uid)
{
memset (m_data->m_data, 0xff, 4);
if (size > 0)
{
DoAddHeader (0, size);
}
}
PacketMetadata::PacketMetadata (PacketMetadata const &o)
: m_data (o.m_data),
m_head (o.m_head),
m_tail (o.m_tail),
m_used (o.m_used),
m_packetUid (o.m_packetUid)
{
NS_ASSERT (m_data != 0);
m_data->m_count++;
}
PacketMetadata &
PacketMetadata::operator = (PacketMetadata const& o)
{
if (m_data == o.m_data)
{
// self assignment
return *this;
}
NS_ASSERT (m_data != 0);
m_data->m_count--;
if (m_data->m_count == 0)
{
PacketMetadata::Recycle (m_data);
}
m_data = o.m_data;
m_head = o.m_head;
m_tail = o.m_tail;
m_used = o.m_used;
m_packetUid = o.m_packetUid;
NS_ASSERT (m_data != 0);
m_data->m_count++;
return *this;
}
PacketMetadata::~PacketMetadata ()
{
NS_ASSERT (m_data != 0);
m_data->m_count--;
if (m_data->m_count == 0)
{
PacketMetadata::Recycle (m_data);
}
}
}; // namespace ns3
#endif /* PACKET_METADATA_H */
+235
View File
@@ -0,0 +1,235 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "packet-printer.h"
namespace ns3 {
PacketPrinter::PacketPrinter ()
: m_forward (true),
m_separator ("")
{}
void
PacketPrinter::PrintForward (void)
{
m_forward = true;
}
void
PacketPrinter::PrintBackward (void)
{
m_forward = false;
}
void
PacketPrinter::SetSeparator (std::string separator)
{
m_separator = separator;
}
void
PacketPrinter::AddPayloadPrinter (PayloadPrinter printer)
{
m_payloadPrinter = printer;
}
void
PacketPrinter::AddDefaultPrinter (DefaultPrinter printer)
{
m_defaultPrinter = printer;
}
PacketPrinter::RegisteredChunks *
PacketPrinter::GetRegisteredChunks (void)
{
static RegisteredChunks registeredChunks;
return &registeredChunks;
}
PacketPrinter
PacketPrinter::GetDefault (void)
{
return *(PacketPrinter::PeekDefault ());
}
PacketPrinter *
PacketPrinter::PeekDefault (void)
{
static PacketPrinter *tmp = PacketPrinter::CreateStaticDefault ();
return tmp;
}
PacketPrinter *
PacketPrinter::CreateStaticDefault (void)
{
static PacketPrinter tmp;
tmp.PrintForward ();
tmp.AddPayloadPrinter (MakeCallback (&PacketPrinter::DoDefaultPrintPayload));
tmp.SetSeparator (" ");
return &tmp;
}
void
PacketPrinter::PrintChunk (uint32_t chunkUid,
Buffer::Iterator start,
std::ostream &os,
uint32_t packetUid,
uint32_t size) const
{
RegisteredChunks *registeredChunks = PacketPrinter::GetRegisteredChunks ();
NS_ASSERT (chunkUid >= 1 && chunkUid/2 <= registeredChunks->size ());
for (PrinterList::const_iterator i = m_printerList.begin (); i != m_printerList.end (); i++)
{
if (i->m_chunkUid == chunkUid)
{
DoPrintCallback cb = (*registeredChunks)[chunkUid/2-1].printCallback;
cb (i->m_printer, start, os, packetUid, size);
return;
}
}
DoGetNameCallback cb = (*registeredChunks)[chunkUid/2-1].getNameCallback;
std::string name = cb ();
struct PacketPrinter::FragmentInformation info;
info.start = 0;
info.end = 0;
if (!m_defaultPrinter.IsNull ())
{
m_defaultPrinter (os, packetUid, size, name, info);
}
}
void
PacketPrinter::PrintChunkFragment (uint32_t chunkUid,
std::ostream &os,
uint32_t packetUid,
uint32_t size,
uint32_t fragmentStart,
uint32_t fragmentEnd) const
{
RegisteredChunks *registeredChunks = PacketPrinter::GetRegisteredChunks ();
NS_ASSERT (chunkUid >= 1 && chunkUid/2 <= registeredChunks->size ());
DoGetNameCallback cb = (*registeredChunks)[chunkUid/2-1].getNameCallback;
std::string name = cb ();
struct PacketPrinter::FragmentInformation info;
info.start = fragmentStart;
info.end = fragmentEnd;
for (PrinterList::const_iterator i = m_printerList.begin (); i != m_printerList.end (); i++)
{
if (i->m_chunkUid == chunkUid)
{
i->m_fragmentPrinter (os, packetUid, size, name, info);
return;
}
}
if (!m_defaultPrinter.IsNull ())
{
m_defaultPrinter (os, packetUid, size, name, info);
}
}
void
PacketPrinter::PrintPayload (std::ostream &os, uint32_t packetUid, uint32_t size,
uint32_t fragmentStart, uint32_t fragmentEnd) const
{
struct PacketPrinter::FragmentInformation info;
info.start = fragmentStart;
info.end = fragmentEnd;
if (!m_payloadPrinter.IsNull ())
{
m_payloadPrinter (os, packetUid, size, info);
}
}
void
PacketPrinter::DoDefaultPrintPayload (std::ostream & os,
uint32_t packetUid,
uint32_t size,
struct PacketPrinter::FragmentInformation info)
{
os << "DATA ("
<< "length " << size - (info.end + info.start);
if (info.start != 0 || info.end != 0)
{
os << " "
<< "trim_start " << info.start << " "
<< "trim_end " << info.end;
}
os << ")";
}
void
PacketPrinter::DoDefaultPrintDefault (std::ostream & os,
uint32_t packetUid,
uint32_t size,
std::string &name,
struct PacketPrinter::FragmentInformation info)
{
NS_ASSERT_MSG (false, "This should never happen because we provide a printer for _all_ chunk types.");
}
void
PacketPrinter::DoDefaultPrintFragment (std::ostream & os,
uint32_t packetUid,
uint32_t size,
std::string &name,
struct PacketPrinter::FragmentInformation info)
{
NS_ASSERT (info.start != 0 || info.end != 0);
os << name << " "
<< "("
<< "length " << size - (info.end + info.start) << " "
<< "trim_start " << info.start << " "
<< "trim_end " << info.end
<< ")"
;
}
void
PacketPrinter::DoAddPrinter (uint32_t uid,
Ptr<CallbackImplBase> printer,
Callback<void,
std::ostream &,
uint32_t,
uint32_t,
std::string &,
struct PacketPrinter::FragmentInformation> fragmentPrinter)
{
struct PacketPrinter::Printer p;
p.m_chunkUid = uid;
p.m_printer = printer;
p.m_fragmentPrinter = fragmentPrinter;
m_printerList.push_back (p);
}
bool
PacketPrinter::IsTrailer (uint32_t uid)
{
RegisteredChunks *registeredChunks = PacketPrinter::GetRegisteredChunks ();
NS_ASSERT (uid >= 1 && uid/2 <= registeredChunks->size ());
bool isHeader = (*registeredChunks)[uid/2-1].isHeader;
return !isHeader;
}
bool
PacketPrinter::IsHeader (uint32_t uid)
{
RegisteredChunks *registeredChunks = PacketPrinter::GetRegisteredChunks ();
NS_ASSERT (uid >= 1 && uid/2 <= registeredChunks->size ());
bool isHeader = (*registeredChunks)[uid/2-1].isHeader;
return isHeader;
}
} // namespace ns3
+318
View File
@@ -0,0 +1,318 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef PACKET_PRINTER_H
#define PACKET_PRINTER_H
#include "ns3/callback.h"
#include "ns3/ptr.h"
#include "buffer.h"
#include <vector>
namespace {
class ItemList;
}
namespace ns3 {
class Chunk;
/**
* \brief hold a list of print callbacks for packet headers and trailers
*
* Users can register in instances of this class print callbacks
* which are used by Packet::Print to print the content of a packet.
*/
class PacketPrinter
{
public:
/**
* \brief indicates how many bytes were trimmed from a header
* or a trailer.
*/
struct FragmentInformation
{
/**
* The number of bytes trimmed from the start of the header or the trailer.
*/
uint32_t start;
/**
* The number of bytes trimmed from the end of the header or the trailer.
*/
uint32_t end;
};
/**
* \brief callback to print payload.
*
* Arguments: output stream, packet uid, size, fragment information
*/
typedef Callback<void,std::ostream &,uint32_t,uint32_t,struct PacketPrinter::FragmentInformation>
PayloadPrinter;
/**
* \brief callback to print fragmented chunks.
*
* Arguments: output stream, packet uid, size, header/trailer name, fragment information
*/
typedef Callback<void,std::ostream &,uint32_t,uint32_t,std::string &,struct PacketPrinter::FragmentInformation>
ChunkFragmentPrinter;
/**
* \brief callback to print chunks for which no specific callback was specified.
*
* Arguments: output stream, packet uid, size, header/trailer name, fragment information
*/
typedef Callback<void,std::ostream&,uint32_t,uint32_t,std::string&,struct PacketPrinter::FragmentInformation>
DefaultPrinter;
PacketPrinter ();
/**
* Print the content of the packet forward.
*/
void PrintForward (void);
/**
* Print the content of the packet backward.
*/
void PrintBackward (void);
void SetSeparator (std::string separator);
/**
* \param printer printer for payload
*/
void AddPayloadPrinter (PayloadPrinter printer);
/**
* \param printer printer for the specified chunk
* \param fragmentPrinter printer for a fragment of the specified chunk
*
* If the user has not specified a callback for a specific header present
* in a packet, the "default" callback is invoked. If no such callback
* was specified, nothing happens.
*/
template <typename T>
void AddHeaderPrinter (Callback<void,std::ostream &,uint32_t,uint32_t,const T *> printer,
ChunkFragmentPrinter fragmentPrinter);
/**
* \param printer printer for the specified chunk
* \param fragmentPrinter printer for a fragment of the specified chunk
*
* If the user has not specified a callback for a specific trailer present
* in a packet, the "default" callback is invoked. If no such callback
* was specified, nothing happens.
*/
template <typename T>
void AddTrailerPrinter (Callback<void,std::ostream &,uint32_t,uint32_t,const T *> printer,
ChunkFragmentPrinter fragmentPrinter);
/**
* \param printer printer for a chunk for which no callback was specified explicitely
*/
void AddDefaultPrinter (DefaultPrinter printer);
private:
friend class PacketMetadata;
typedef void (*DoPrintCallback) (Ptr<CallbackImplBase>, Buffer::Iterator, std::ostream &,
uint32_t, uint32_t);
typedef std::string (*DoGetNameCallback) (void);
struct Printer
{
uint32_t m_chunkUid;
Ptr<CallbackImplBase> m_printer;
Callback<void,std::ostream &,uint32_t,uint32_t,std::string &,struct PacketPrinter::FragmentInformation>
m_fragmentPrinter;
};
struct RegisteredChunk
{
DoPrintCallback printCallback;
DoGetNameCallback getNameCallback;
bool isHeader;
};
typedef std::vector<struct PacketPrinter::Printer> PrinterList;
typedef std::vector<struct RegisteredChunk> RegisteredChunks;
static PacketPrinter GetDefault (void);
static PacketPrinter *PeekDefault (void);
static PacketPrinter *CreateStaticDefault (void);
static void DoDefaultPrintPayload (std::ostream & os,
uint32_t packetUid,
uint32_t size,
struct PacketPrinter::FragmentInformation info);
static void DoDefaultPrintDefault (std::ostream & os,
uint32_t packetUid,
uint32_t size,
std::string &name,
struct PacketPrinter::FragmentInformation info);
template <typename T>
static void DoDefaultPrint (std::ostream &os, uint32_t packetUid, uint32_t size, const T *chunk);
static void DoDefaultPrintFragment (std::ostream & os,
uint32_t packetUid,
uint32_t size,
std::string &name,
struct PacketPrinter::FragmentInformation info);
template <typename T>
static void DoPrint (Ptr<CallbackImplBase> callbackPrinter,
Buffer::Iterator i,
std::ostream &os,
uint32_t packetUid,
uint32_t size);
template <typename T>
static std::string DoGetName (void);
template <typename T>
static uint32_t GetTrailerUid (void);
template <typename T>
static uint32_t GetHeaderUid (void);
template <typename T>
static uint32_t AllocateUid (bool isHeader);
static RegisteredChunks *GetRegisteredChunks (void);
static bool IsTrailer (uint32_t uid);
static bool IsHeader (uint32_t uid);
void PrintChunk (uint32_t uid,
Buffer::Iterator i,
std::ostream &os,
uint32_t packetUid,
uint32_t size) const;
void PrintChunkFragment (uint32_t uid,
std::ostream &os,
uint32_t packetUid,
uint32_t size,
uint32_t fragmentStart,
uint32_t fragmentEnd) const;
void PrintPayload (std::ostream &os, uint32_t packetUid, uint32_t size,
uint32_t fragmentStart, uint32_t fragmentEnd) const;
void DoAddPrinter (uint32_t uid,
Ptr<CallbackImplBase> printer,
Callback<void,
std::ostream &,
uint32_t,
uint32_t,
std::string &,
struct PacketPrinter::FragmentInformation> fragmentPrinter);
static PacketPrinter m_defaultPacketPrinter;
PrinterList m_printerList;
PayloadPrinter m_payloadPrinter;
DefaultPrinter m_defaultPrinter;
bool m_forward;
std::string m_separator;
};
} // namespace ns3
namespace ns3 {
template <typename T>
void
PacketPrinter::AddHeaderPrinter (Callback<void,std::ostream &, uint32_t, uint32_t, const T *> printer,
Callback<void,
std::ostream &,
uint32_t,
uint32_t,
std::string &,
struct PacketPrinter::FragmentInformation> fragmentPrinter)
{
static uint32_t uid = PacketPrinter::GetHeaderUid<T> ();
DoAddPrinter (uid, printer.GetImpl (), fragmentPrinter);
}
template <typename T>
void
PacketPrinter::AddTrailerPrinter (Callback<void,std::ostream &, uint32_t, uint32_t, const T *> printer,
Callback<void,
std::ostream &,
uint32_t,
uint32_t,
std::string &,
struct PacketPrinter::FragmentInformation> fragmentPrinter)
{
static uint32_t uid = PacketPrinter::GetTrailerUid<T> ();
DoAddPrinter (uid, printer.GetImpl (), fragmentPrinter);
}
template <typename T>
void
PacketPrinter::DoPrint (Ptr<CallbackImplBase> printerCallback,
Buffer::Iterator i,
std::ostream &os,
uint32_t packetUid,
uint32_t size)
{
T chunk = T ();
chunk.Deserialize (i);
Callback<void,std::ostream&,uint32_t,uint32_t,const T*> callback;
callback.Assign (printerCallback);
callback (os, packetUid, size, &chunk);
}
template <typename T>
std::string
PacketPrinter::DoGetName (void)
{
T chunk = T ();
return chunk.GetName ();
}
template <typename T>
uint32_t
PacketPrinter::GetHeaderUid (void)
{
static uint32_t uid = PacketPrinter::AllocateUid<T> (true);
return uid;
}
template <typename T>
uint32_t
PacketPrinter::GetTrailerUid (void)
{
static uint32_t uid = PacketPrinter::AllocateUid<T> (false);
return uid;
}
template <typename T>
uint32_t
PacketPrinter::AllocateUid (bool isHeader)
{
RegisteredChunks *chunks = PacketPrinter::GetRegisteredChunks ();
RegisteredChunk chunk;
chunk.printCallback = &PacketPrinter::DoPrint<T>;
chunk.getNameCallback = &PacketPrinter::DoGetName<T>;
chunk.isHeader = isHeader;
chunks->push_back (chunk);
uint32_t uid = chunks->size () * 2;
PacketPrinter::PeekDefault ()->DoAddPrinter (uid,
MakeCallback (&PacketPrinter::DoDefaultPrint<T>).GetImpl (),
MakeCallback (&PacketPrinter::DoDefaultPrintFragment));
return uid;
}
template <typename T>
void
PacketPrinter::DoDefaultPrint (std::ostream &os, uint32_t packetUid, uint32_t size, const T *chunk)
{
os << chunk->GetName () << " ";
chunk->Print (os);
}
} // namespace ns3
#endif /* PACKET_PRINTER_H */
+201
View File
@@ -0,0 +1,201 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2005,2006 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "packet.h"
#include "packet-printer.h"
#include "ns3/assert.h"
namespace ns3 {
uint32_t Packet::m_globalUid = 0;
Packet::Packet ()
: m_buffer (),
m_metadata (m_globalUid, 0)
{
m_globalUid++;
}
Packet::Packet (uint32_t size)
: m_buffer (size),
m_metadata (m_globalUid, size)
{
m_globalUid++;
}
Packet::Packet (uint8_t const*buffer, uint32_t size)
: m_buffer (),
m_metadata (m_globalUid, size)
{
m_globalUid++;
m_buffer.AddAtStart (size);
Buffer::Iterator i = m_buffer.Begin ();
i.Write (buffer, size);
}
Packet::Packet (Buffer buffer, Tags tags, PacketMetadata metadata)
: m_buffer (buffer),
m_tags (tags),
m_metadata (metadata)
{}
Packet
Packet::CreateFragment (uint32_t start, uint32_t length) const
{
Buffer buffer = m_buffer.CreateFragment (start, length);
NS_ASSERT (m_buffer.GetSize () >= start + length);
uint32_t end = m_buffer.GetSize () - (start + length);
PacketMetadata metadata = m_metadata.CreateFragment (start, end);
return Packet (buffer, m_tags, metadata);
}
uint32_t
Packet::GetSize (void) const
{
return m_buffer.GetSize ();
}
void
Packet::AddAtEnd (Packet packet)
{
packet.m_buffer.TransformIntoRealBuffer ();
m_buffer.TransformIntoRealBuffer ();
Buffer src = packet.m_buffer;
m_buffer.AddAtEnd (src.GetSize ());
Buffer::Iterator destStart = m_buffer.End ();
destStart.Prev (src.GetSize ());
destStart.Write (src.Begin (), src.End ());
/**
* XXX: we might need to merge the tag list of the
* other packet into the current packet.
*/
m_metadata.AddAtEnd (packet.m_metadata);
}
void
Packet::AddPaddingAtEnd (uint32_t size)
{
m_buffer.AddAtEnd (size);
m_metadata.AddPaddingAtEnd (size);
}
void
Packet::RemoveAtEnd (uint32_t size)
{
m_buffer.RemoveAtEnd (size);
m_metadata.RemoveAtEnd (size);
}
void
Packet::RemoveAtStart (uint32_t size)
{
m_buffer.RemoveAtStart (size);
m_metadata.RemoveAtStart (size);
}
void
Packet::RemoveAllTags (void)
{
m_tags.RemoveAll ();
}
uint8_t const *
Packet::PeekData (void) const
{
return m_buffer.PeekData ();
}
uint32_t
Packet::GetUid (void) const
{
return m_metadata.GetUid ();
}
void
Packet::Print (std::ostream &os) const
{
m_metadata.PrintDefault (os, m_buffer);
}
void
Packet::Print (std::ostream &os, const PacketPrinter &printer) const
{
m_metadata.Print (os, m_buffer, printer);
}
void
Packet::EnableMetadata (void)
{
PacketMetadata::Enable ();
}
}; // namespace ns3
#ifdef RUN_SELF_TESTS
#include "ns3/test.h"
#include <string>
namespace ns3 {
class PacketTest: public Test {
public:
virtual bool RunTests (void);
PacketTest ();
};
PacketTest::PacketTest ()
: Test ("Packet") {}
bool
PacketTest::RunTests (void)
{
bool ok = true;
Packet pkt1 (reinterpret_cast<const uint8_t*> ("hello"), 5);
Packet pkt2 (reinterpret_cast<const uint8_t*> (" world"), 6);
Packet packet;
packet.AddAtEnd (pkt1);
packet.AddAtEnd (pkt2);
if (packet.GetSize () != 11)
{
Failure () << "expected size 11, got " << packet.GetSize () << std::endl;
ok = false;
}
std::string msg = std::string (reinterpret_cast<const char *>(packet.PeekData ()),
packet.GetSize ());
if (msg != "hello world")
{
Failure () << "expected size 'hello world', got " << msg << std::endl;
ok = false;
}
return ok;
}
static PacketTest gPacketTest;
}; // namespace ns3
#endif /* RUN_SELF_TESTS */
+379
View File
@@ -0,0 +1,379 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2005,2006 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef PACKET_H
#define PACKET_H
#include <stdint.h>
#include "buffer.h"
#include "header.h"
#include "trailer.h"
#include "tags.h"
#include "packet-metadata.h"
#include "ns3/callback.h"
#include "ns3/assert.h"
namespace ns3 {
class PacketPrinter;
/**
* \brief network packets
*
* Each network packet contains a byte buffer and a list of tags.
* - The byte buffer stores the serialized content of the headers and trailers
* added to a packet. The serialized representation of these headers is expected
* to match that of real network packets bit for bit (although nothing
* forces you to do this) which means that the content of a packet buffer
* is expected to be that of a real packet.
* - The list of tags stores an arbitrarily large set of arbitrary
* user-provided data structures in the packet: only one instance of
* each type of data structure is allowed in a list of tags.
* These tags typically contain per-packet cross-layer information or
* flow identifiers. Each tag stored in the tag list can be at most
* 16 bytes big. Trying to attach bigger data structures will trigger
* crashes at runtime.
*
* Implementing a new type of Header for a new protocol is pretty easy
* and is a matter of creating a subclass of the ns3::Header base class,
* and implementing the 4 pure virtual methods defined in ns3::Header.
* Sample code which shows how to create such a new Header, how to use
* it, and how to manipulate tags is shown below:
* \include samples/main-packet.cc
*
* The current implementation of the byte buffers and tag list is based
* on COW (Copy On Write. An introduction to COW can be found in Scott
* Meyer's "More Effective C++", items 17 and 29). What this means is that
* copying packets without modifying them is very cheap (in terms of cpu
* and memory usage) and modifying them can be also very cheap. What is
* key for proper COW implementations is being
* able to detect when a given modification of the state of a packet triggers
* a full copy of the data prior to the modification: COW systems need
* to detect when an operation is "dirty".
*
* Dirty operations:
* - ns3::Packet::RemoveTag
* - ns3::Packet::Add
* - both versions of ns3::Packet::AddAtEnd
*
* Non-dirty operations:
* - ns3::Packet::AddTag
* - ns3::Packet::RemoveAllTags
* - ns3::Packet::PeekTag
* - ns3::Packet::Peek
* - ns3::Packet::Remove
* - ns3::Packet::CreateFragment
* - ns3::Packet::RemoveAtStart
* - ns3::Packet::RemoveAtEnd
*
* Dirty operations will always be slower than non-dirty operations,
* sometimes by several orders of magnitude. However, even the
* dirty operations have been optimized for common use-cases which
* means that most of the time, these operations will not trigger
* data copies and will thus be still very fast.
*/
class Packet {
public:
/**
* Create an empty packet with a new uid (as returned
* by getUid).
*/
Packet ();
/**
* Create a packet with a zero-filled payload.
* The memory necessary for the payload is not allocated:
* it will be allocated at any later point if you attempt
* to fragment this packet or to access the zero-filled
* bytes. The packet is allocated with a new uid (as
* returned by getUid).
*
* \param size the size of the zero-filled payload
*/
Packet (uint32_t size);
/**
* Create a packet with payload filled with the content
* of this buffer. The input data is copied: the input
* buffer is untouched.
*
* \param buffer the data to store in the packet.
* \param size the size of the input buffer.
*/
Packet (uint8_t const*buffer, uint32_t size);
/**
* Create a new packet which contains a fragment of the original
* packet. The returned packet shares the same uid as this packet.
*
* \param start offset from start of packet to start of fragment to create
* \param length length of fragment to create
* \returns a fragment of the original packet
*/
Packet CreateFragment (uint32_t start, uint32_t length) const;
/**
* \returns the size in bytes of the packet (including the zero-filled
* initial payload)
*/
uint32_t GetSize (void) const;
/**
* Add header to this packet. This method invokes the
* ns3::Chunk::GetSerializedSize and ns3::Chunk::SerializeTo
* methods to reserve space in the buffer and request the
* header to serialize itself in the packet buffer.
*
* \param header a reference to the header to add to this packet.
*/
template <typename T>
void AddHeader (T const &header);
/**
* Deserialize and remove the header from the internal buffer.
* This method invokes ns3::Chunk::DeserializeFrom.
*
* \param header a reference to the header to remove from the internal buffer.
* \returns the number of bytes removed from the packet.
*/
template <typename T>
uint32_t RemoveHeader (T &header);
/**
* Add trailer to this packet. This method invokes the
* ns3::Chunk::GetSerializedSize and ns3::Trailer::serializeTo
* methods to reserve space in the buffer and request the trailer
* to serialize itself in the packet buffer.
*
* \param trailer a reference to the trailer to add to this packet.
*/
template <typename T>
void AddTrailer (T const &trailer);
/**
* Remove a deserialized trailer from the internal buffer.
* This method invokes the ns3::Chunk::DeserializeFrom method.
*
* \param trailer a reference to the trailer to remove from the internal buffer.
* \returns the number of bytes removed from the end of the packet.
*/
template <typename T>
uint32_t RemoveTrailer (T &trailer);
/**
* Attach a tag to this packet. The tag is fully copied
* in a packet-specific internal buffer. This operation
* is expected to be really fast.
*
* \param tag a pointer to the tag to attach to this packet.
*/
template <typename T>
void AddTag (T const &tag);
/**
* Remove a tag from this packet. The data stored internally
* for this tag is copied in the input tag if an instance
* of this tag type is present in the internal buffer. If this
* tag type is not present, the input tag is not modified.
*
* This operation can be potentially slow and might trigger
* unexpectedly large memory allocations. It is thus
* usually a better idea to create a copy of this packet,
* and invoke removeAllTags on the copy to remove all
* tags rather than remove the tags one by one from a packet.
*
* \param tag a pointer to the tag to remove from this packet
* \returns true if an instance of this tag type is stored
* in this packet, false otherwise.
*/
template <typename T>
bool RemoveTag (T &tag);
/**
* Copy a tag stored internally to the input tag. If no instance
* of this tag is present internally, the input tag is not modified.
*
* \param tag a pointer to the tag to read from this packet
* \returns true if an instance of this tag type is stored
* in this packet, false otherwise.
*/
template <typename T>
bool PeekTag (T &tag) const;
/**
* Remove all the tags stored in this packet. This operation is
* much much faster than invoking removeTag n times.
*/
void RemoveAllTags (void);
/**
* Concatenate the input packet at the end of the current
* packet. This does not alter the uid of either packet.
*
* \param packet packet to concatenate
*/
void AddAtEnd (Packet packet);
/**
* \param size number of padding bytes to add.
*/
void AddPaddingAtEnd (uint32_t size);
/**
* Remove size bytes from the end of the current packet
* It is safe to remove more bytes that what is present in
* the packet.
*
* \param size number of bytes from remove
*/
void RemoveAtEnd (uint32_t size);
/**
* Remove size bytes from the start of the current packet.
* It is safe to remove more bytes that what is present in
* the packet.
*
* \param size number of bytes from remove
*/
void RemoveAtStart (uint32_t size);
/**
* If you try to change the content of the buffer
* returned by this method, you will die.
*
* \returns a pointer to the internal buffer of the packet.
*/
uint8_t const *PeekData (void) const;
/**
* A packet is allocated a new uid when it is created
* empty or with zero-filled payload.
*
* \returns an integer identifier which uniquely
* identifies this packet.
*/
uint32_t GetUid (void) const;
/**
* \param os output stream in which the data should be printed.
*
* Iterate over the headers and trailers present in this packet,
* from the first header to the last trailer and invoke, for
* each of them, the user-provided method Header::DoPrint or
* Trailer::DoPrint methods.
*/
void Print (std::ostream &os) const;
/**
* \param os output stream in which the data should be printed.
* \param printer the output formatter to use to print
* the content of this packet.
*
* Iterate over the headers and trailers present in this packet,
* either in the "forward" (first header to last trailer) or in
* the "backward" (last trailer to first header) direction, as
* specified by the PacketPrinter::PrintForward or the
* PacketPrinter::PrintBackward methods. For each header, trailer,
* or fragment of a header or a trailer, invoke the user-specified
* print callback stored in the specified PacketPrinter.
*/
void Print (std::ostream &os, const PacketPrinter &printer) const;
/**
* By default, packets do not keep around enough metadata to
* perform the operations requested by the Print methods. If you
* want to be able to invoke any of the two ::Print methods,
* you need to invoke this method at least once during the
* simulation setup and before any packet is created.
*
* The packet metadata is also used to perform extensive
* sanity checks at runtime when performing operations on a
* Packet. For example, this metadata is used to verify that
* when you remove a header from a packet, this same header
* was actually present at the front of the packet. These
* errors will be detected and will abort the program.
*/
static void EnableMetadata (void);
private:
Packet (Buffer buffer, Tags tags, PacketMetadata metadata);
Buffer m_buffer;
Tags m_tags;
PacketMetadata m_metadata;
static uint32_t m_globalUid;
};
}; // namespace ns3
/**************************************************
Start of implementation of templates defined
above
*************************************************/
namespace ns3 {
template <typename T>
void
Packet::AddHeader (T const &header)
{
NS_ASSERT_MSG (dynamic_cast<Header const *> (&header) != 0,
"Must pass Header subclass to Packet::AddHeader");
uint32_t size = header.GetSize ();
m_buffer.AddAtStart (size);
header.Serialize (m_buffer.Begin ());
m_metadata.AddHeader (header, size);
}
template <typename T>
uint32_t
Packet::RemoveHeader (T &header)
{
NS_ASSERT_MSG (dynamic_cast<Header const *> (&header) != 0,
"Must pass Header subclass to Packet::RemoveHeader");
uint32_t deserialized = header.Deserialize (m_buffer.Begin ());
m_buffer.RemoveAtStart (deserialized);
m_metadata.RemoveHeader (header, deserialized);
return deserialized;
}
template <typename T>
void
Packet::AddTrailer (T const &trailer)
{
NS_ASSERT_MSG (dynamic_cast<Trailer const *> (&trailer) != 0,
"Must pass Trailer subclass to Packet::AddTrailer");
uint32_t size = trailer.GetSize ();
m_buffer.AddAtEnd (size);
Buffer::Iterator end = m_buffer.End ();
trailer.Serialize (end);
m_metadata.AddTrailer (trailer, size);
}
template <typename T>
uint32_t
Packet::RemoveTrailer (T &trailer)
{
NS_ASSERT_MSG (dynamic_cast<Trailer const *> (&trailer) != 0,
"Must pass Trailer subclass to Packet::RemoveTrailer");
uint32_t deserialized = trailer.Deserialize (m_buffer.End ());
m_buffer.RemoveAtEnd (deserialized);
m_metadata.RemoveTrailer (trailer, deserialized);
return deserialized;
}
template <typename T>
void Packet::AddTag (T const& tag)
{
m_tags.Add (tag);
}
template <typename T>
bool Packet::RemoveTag (T & tag)
{
return m_tags.Remove (tag);
}
template <typename T>
bool Packet::PeekTag (T & tag) const
{
return m_tags.Peek (tag);
}
}; // namespace ns3
#endif /* PACKET_H */
+123
View File
@@ -0,0 +1,123 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2005,2006 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
/*
* Documentation kindly pointed out by Tom Henderson:
* http://wiki.ethereal.com/Development/LibpcapFileFormat
*/
#include <fstream>
#include "ns3/simulator.h"
#include "pcap-writer.h"
#include "packet.h"
namespace ns3 {
enum {
PCAP_ETHERNET = 1,
PCAP_RAW_IP = 101,
PCAP_80211 = 105,
};
PcapWriter::PcapWriter ()
{
m_writer = 0;
}
PcapWriter::~PcapWriter ()
{
delete m_writer;
}
void
PcapWriter::Open (std::string const &name)
{
m_writer = new std::ofstream ();
m_writer->open (name.c_str ());
}
void
PcapWriter::WriteEthernetHeader (void)
{
WriteHeader (PCAP_ETHERNET);
}
void
PcapWriter::WriteIpHeader (void)
{
WriteHeader (PCAP_RAW_IP);
}
void
PcapWriter::WriteWifiHeader (void)
{
WriteHeader (PCAP_80211);
}
void
PcapWriter::WriteHeader (uint32_t network)
{
Write32 (0xa1b2c3d4);
Write16 (2);
Write16 (4);
Write32 (0);
Write32 (0);
Write32 (0xffff);
Write32 (network);
}
void
PcapWriter::WritePacket (Packet const packet)
{
if (m_writer != 0)
{
uint64_t current = Simulator::Now ().GetMicroSeconds ();
uint64_t s = current / 1000000;
uint64_t us = current % 1000000;
Write32 (s & 0xffffffff);
Write32 (us & 0xffffffff);
Write32 (packet.GetSize ());
Write32 (packet.GetSize ());
WriteData (packet.PeekData (), packet.GetSize ());
}
}
void
PcapWriter::WriteData (uint8_t const*buffer, uint32_t size)
{
m_writer->write ((char const *)buffer, size);
}
void
PcapWriter::Write32 (uint32_t data)
{
WriteData ((uint8_t*)&data, 4);
}
void
PcapWriter::Write16 (uint16_t data)
{
WriteData((uint8_t*)&data, 2);
}
}; // namespace ns3
+78
View File
@@ -0,0 +1,78 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2005,2006 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef PCAP_WRITER_H
#define PCAP_WRITER_H
#include "ns3/callback.h"
#include <stdint.h>
#include "packet.h"
namespace ns3 {
/**
* \brief Pcap output for Packet logger
*
* Log Packets to a file in pcap format which can be
* read by pcap readers.
*/
class PcapWriter {
public:
PcapWriter ();
~PcapWriter ();
/**
* \param name the name of the file to store packet log into.
* This method creates the file if it does not exist. If it
* exists, the file is emptied.
*/
void Open (std::string const &name);
/**
* Write a pcap header in the output file which specifies
* that the content of the file will Packets with
* Ethernet/LLC/SNAP encapsulation. This method should
* be invoked before ns3::PcapWriter::writePacket and after
* ns3::PcapWriter::open.
*/
void WriteEthernetHeader (void);
void WriteIpHeader (void);
void WriteWifiHeader (void);
/**
* \param packet packet to write to output file
*/
void WritePacket (Packet const packet);
private:
void WriteData (uint8_t const*buffer, uint32_t size);
void Write32 (uint32_t data);
void Write16 (uint16_t data);
void WriteHeader (uint32_t network);
std::ofstream *m_writer;
Callback<void,uint8_t *,uint32_t> m_writeCallback;
};
}; // namespace ns3
#endif /* PCAP_WRITER_H */
+68
View File
@@ -0,0 +1,68 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2006 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "stream-tracer.h"
#include "ns3/test.h"
#include <iostream>
#ifdef RUN_SELF_TESTS
namespace {
class TestStreamTracer : public ns3::Test {
public:
TestStreamTracer ();
virtual bool RunTests (void);
};
static TestStreamTracer gTestStream;
TestStreamTracer::TestStreamTracer ()
: Test ("StreamTracer")
{}
bool
TestStreamTracer::RunTests (void)
{
bool ok = true;
ns3::StreamTracer trace;
//trace.setStream (&std::cout);
trace << 1;
trace << " X ";
trace << 1.0;
trace << std::endl;
trace << "test ";
trace << 1 << " test";
trace << "test "
<< 1.0 << " "
<< 0xdeadbead
<< std::endl;
trace << "0x" << std::hex
<< 0xdeadbeaf
<< std::dec << " "
<< 0xdeadbeaf
<< std::endl;
return ok;
}
}; // namespace ns3
#endif /* RUN_SELF_TESTS */
+76
View File
@@ -0,0 +1,76 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2006 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef STREAM_TRACER_H
#define STREAM_TRACER_H
#include <ostream>
namespace ns3 {
/**
* \brief log arbitrary data to std::ostreams
*
* Whenever operator << is invoked on this class,
* it is forwarded to the stored std::ostream output
* stream (if there is one).
*/
class StreamTracer {
public:
StreamTracer ()
: m_os (0) {}
template <typename T>
StreamTracer &operator << (T const&v) {
if (m_os != 0)
{
(*m_os) << v;
}
return *this;
}
template <typename T>
StreamTracer &operator << (T &v) {
if (m_os != 0)
{
(*m_os) << v;
}
return *this;
}
StreamTracer &operator << (std::ostream &(*v) (std::ostream &)) {
if (m_os != 0)
{
(*m_os) << v;
}
return *this;
}
/**
* \param os the output stream to store
*/
void SetStream (std::ostream * os) {
m_os = os;
}
private:
std::ostream *m_os;
};
}; // namespace ns3
#endif /* TRACER_STREAM_H */
+242
View File
@@ -0,0 +1,242 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2006 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef SV_TRACE_SOURCE_H
#define SV_TRACE_SOURCE_H
#include "callback-trace-source.h"
#include <stdint.h>
namespace ns3 {
class SVTraceSourceBase {
public:
typedef CallbackTraceSource<int64_t, int64_t> ChangeNotifyCallback;
SVTraceSourceBase () {}
SVTraceSourceBase (SVTraceSourceBase const &o) {}
SVTraceSourceBase &operator = (SVTraceSourceBase const &o) {
return *this;
}
~SVTraceSourceBase () {}
void AddCallback (CallbackBase const & callback, TraceContext const & context) {
m_callback.AddCallback (callback, context);
}
void RemoveCallback (CallbackBase const & callback) {
m_callback.RemoveCallback (callback);
}
protected:
void Notify (int64_t oldVal, int64_t newVal) {
if (oldVal != newVal)
{
m_callback (oldVal, newVal);
}
}
private:
ChangeNotifyCallback m_callback;
};
template <typename T>
class UVTraceSource;
/**
* \brief trace variables of type "signed integer"
* \ingroup lowleveltracing
*
* This template class implements a POD type: it
* behaves like any other variable of type "signed integer"
* except that it also reports any changes to its
* value with its internal callback.
*
* To instantiate a 32-bit signed variable (to store
* a TCP counter for example), you would create a variable of type
* ns3::UVTraceSource<int32_t> :
\code
#include <stdint.h>
#include "ns3/sv-trace-source.h"
ns3::SVTraceSource<uint16_t> var;
\endcode
* and you would use it like any other variable of type int32_t:
\code
var += 12;
var = 10;
var = -10;
\endcode
*/
template <typename T>
class SVTraceSource : public SVTraceSourceBase {
public:
SVTraceSource ()
: m_var (0)
{}
SVTraceSource (T const &var)
: m_var (var)
{}
SVTraceSource &operator = (SVTraceSource const &o) {
Assign (o.Get ());
return *this;
}
template <typename TT>
SVTraceSource &operator = (SVTraceSource<TT> const &o) {
Assign (o.Get ());
return *this;
}
template <typename TT>
SVTraceSource &operator = (UVTraceSource<TT> const &o) {
Assign (o.Get ());
return *this;
}
SVTraceSource &operator++ () {
Assign (Get () + 1);
return *this;
}
SVTraceSource &operator-- () {
Assign (Get () - 1);
return *this;
}
SVTraceSource operator++ (int) {
SVTraceSource old (*this);
++*this;
return old;
}
SVTraceSource operator-- (int) {
SVTraceSource old (*this);
--*this;
return old;
}
operator T () const {
return Get ();
}
void Assign (T var) {
Notify (m_var, var);
m_var = var;
}
T Get (void) const {
return m_var;
}
private:
T m_var;
};
template <typename T>
SVTraceSource<T> &operator += (SVTraceSource<T> &lhs, SVTraceSource<T> const &rhs) {
lhs.Assign (lhs.Get () + rhs.Get ());
return lhs;
}
template <typename T>
SVTraceSource<T> &operator -= (SVTraceSource<T> &lhs, SVTraceSource<T> const &rhs) {
lhs.Assign (lhs.Get () - rhs.Get ());
return lhs;
}
template <typename T>
SVTraceSource<T> &operator *= (SVTraceSource<T> &lhs, SVTraceSource<T> const &rhs) {
lhs.Assign (lhs.Get () * rhs.Get ());
return lhs;
}
template <typename T>
SVTraceSource<T> &operator /= (SVTraceSource<T> &lhs, SVTraceSource<T> const &rhs) {
lhs.Assign (lhs.Get () / rhs.Get ());
return lhs;
}
template <typename T>
SVTraceSource<T> &operator <<= (SVTraceSource<T> &lhs, SVTraceSource<T> const &rhs) {
lhs.Assign (lhs.Get () << rhs.Get ());
return lhs;
}
template <typename T>
SVTraceSource<T> &operator >>= (SVTraceSource<T> &lhs, SVTraceSource<T> const &rhs) {
lhs.Assign (lhs.Get () >> rhs.Get ());
return lhs;
}
template <typename T>
SVTraceSource<T> &operator &= (SVTraceSource<T> &lhs, SVTraceSource<T> const &rhs) {
lhs.Assign (lhs.Get () & rhs.Get ());
return lhs;
}
template <typename T>
SVTraceSource<T> &operator |= (SVTraceSource<T> &lhs, SVTraceSource<T> const &rhs) {
lhs.Assign (lhs.Get () | rhs.Get ());
return lhs;
}
template <typename T>
SVTraceSource<T> &operator ^= (SVTraceSource<T> &lhs, SVTraceSource<T> const &rhs) {
lhs.Assign (lhs.Get () ^ rhs.Get ());
return lhs;
}
template <typename T, typename U>
SVTraceSource<T> &operator += (SVTraceSource<T> &lhs, U const &rhs) {
lhs.Assign (lhs.Get () + rhs);
return lhs;
}
template <typename T, typename U>
SVTraceSource<T> &operator -= (SVTraceSource<T> &lhs, U const &rhs) {
lhs.Assign (lhs.Get () - rhs);
return lhs;
}
template <typename T, typename U>
SVTraceSource<T> &operator *= (SVTraceSource<T> &lhs, U const &rhs) {
lhs.Assign (lhs.Get () * rhs);
return lhs;
}
template <typename T, typename U>
SVTraceSource<T> &operator /= (SVTraceSource<T> &lhs, U const &rhs) {
lhs.Assign (lhs.Get () / rhs);
return lhs;
}
template <typename T, typename U>
SVTraceSource<T> &operator <<= (SVTraceSource<T> &lhs, U const &rhs) {
lhs.Assign (lhs.Get () << rhs);
return lhs;
}
template <typename T, typename U>
SVTraceSource<T> &operator >>= (SVTraceSource<T> &lhs, U const &rhs) {
lhs.Assign (lhs.Get () >> rhs);
return lhs;
}
template <typename T, typename U>
SVTraceSource<T> &operator &= (SVTraceSource<T> &lhs, U const &rhs) {
lhs.Assign (lhs.Get () & rhs);
return lhs;
}
template <typename T, typename U>
SVTraceSource<T> &operator |= (SVTraceSource<T> &lhs, U const &rhs) {
lhs.Assign (lhs.Get () | rhs);
return lhs;
}
template <typename T, typename U>
SVTraceSource<T> &operator ^= (SVTraceSource<T> &lhs, U const &rhs) {
lhs.Assign (lhs.Get () ^ rhs);
return lhs;
}
}; // namespace ns3
#endif /* SV_TRACE_SOURCE_H */
+452
View File
@@ -0,0 +1,452 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2006 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "tags.h"
#include <string.h>
namespace ns3 {
TagRegistry *
TagRegistry::GetInstance (void)
{
static TagRegistry registry;
return &registry;
}
TagRegistry::TagRegistry ()
: m_sorted (false)
{}
void
TagRegistry::Record (std::string uuid, PrettyPrinter prettyPrinter, Destructor destructor)
{
NS_ASSERT (!m_sorted);
struct TagInfoItem item;
item.uuid = uuid;
item.printer = prettyPrinter;
item.destructor = destructor;
m_registry.push_back (item);
}
bool
TagRegistry::CompareItem (const struct TagInfoItem &a, const struct TagInfoItem &b)
{
return a.uuid < b.uuid;
}
uint32_t
TagRegistry::LookupUid (std::string uuid)
{
if (!m_sorted)
{
std::sort (m_registry.begin (), m_registry.end (), &TagRegistry::CompareItem);
m_sorted = true;
}
NS_ASSERT (m_sorted);
uint32_t uid = 1;
for (TagsDataCI i = m_registry.begin (); i != m_registry.end (); i++)
{
if (i->uuid == uuid)
{
return uid;
}
uid++;
}
// someone asked for a uid for an unregistered uuid.
NS_ASSERT (!"You tried to use unregistered tag: make sure you create an instance of type TagRegistration<YouTagType>.");
// quiet compiler
return 0;
}
void
TagRegistry::PrettyPrint (uint32_t uid, uint8_t buf[Tags::SIZE], std::ostream &os)
{
NS_ASSERT (uid > 0);
uint32_t index = uid - 1;
NS_ASSERT (m_registry.size () > index);
PrettyPrinter prettyPrinter = m_registry[index].printer;
if (prettyPrinter != 0)
{
prettyPrinter (buf, os);
}
}
void
TagRegistry::Destruct (uint32_t uid, uint8_t buf[Tags::SIZE])
{
NS_ASSERT (uid > 0);
uint32_t index = uid - 1;
NS_ASSERT (m_registry.size () > index);
Destructor destructor = m_registry[index].destructor;
NS_ASSERT (destructor != 0);
destructor (buf);
}
#ifdef USE_FREE_LIST
struct Tags::TagData *Tags::gFree = 0;
uint32_t Tags::gN_free = 0;
struct Tags::TagData *
Tags::AllocData (void)
{
struct Tags::TagData *retval;
if (gFree != 0)
{
retval = gFree;
gFree = gFree->m_next;
gN_free--;
}
else
{
retval = new struct Tags::TagData ();
}
return retval;
}
void
Tags::FreeData (struct TagData *data)
{
if (gN_free > 1000)
{
delete data;
return;
}
gN_free++;
data->m_next = gFree;
data->m_id = 0;
gFree = data;
}
#else
struct Tags::TagData *
Tags::AllocData (void)
{
struct Tags::TagData *retval;
retval = new struct Tags::TagData ();
return retval;
}
void
Tags::FreeData (struct TagData *data)
{
delete data;
}
#endif
bool
Tags::Remove (uint32_t id)
{
bool found = false;
for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next)
{
if (cur->m_id == id)
{
found = true;
}
}
if (!found)
{
return false;
}
struct TagData *start = 0;
struct TagData **prevNext = &start;
for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next)
{
if (cur->m_id == id)
{
/**
* XXX
* Note: I believe that we could optimize this to
* avoid copying each TagData located after the target id
* and just link the already-copied list to the next tag.
*/
continue;
}
struct TagData *copy = AllocData ();
copy->m_id = cur->m_id;
copy->m_count = 1;
copy->m_next = 0;
memcpy (copy->m_data, cur->m_data, Tags::SIZE);
*prevNext = copy;
prevNext = &copy->m_next;
}
*prevNext = 0;
RemoveAll ();
m_next = start;
return true;
}
void
Tags::PrettyPrint (std::ostream &os)
{
for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next)
{
TagRegistry::GetInstance ()->PrettyPrint (cur->m_id, cur->m_data, os);
}
}
}; // namespace ns3
#ifdef RUN_SELF_TESTS
#include "ns3/test.h"
#include <iomanip>
#include <iostream>
namespace ns3 {
static bool g_a;
static bool g_b;
static bool g_c;
static bool g_z;
class TagsTest : Test {
public:
TagsTest ();
virtual ~TagsTest ();
virtual bool RunTests (void);
};
struct myTagA {
uint8_t a;
};
struct myTagB {
uint32_t b;
};
struct myTagC {
uint8_t c [Tags::SIZE];
};
struct myInvalidTag {
uint8_t invalid [Tags::SIZE+1];
};
struct myTagZ {
uint8_t z;
};
class MySmartTag
{
public:
MySmartTag ()
{
//std::cout << "construct" << std::endl;
}
MySmartTag (const MySmartTag &o)
{
//std::cout << "copy" << std::endl;
}
~MySmartTag ()
{
//std::cout << "destruct" << std::endl;
}
MySmartTag &operator = (const MySmartTag &o)
{
//std::cout << "assign" << std::endl;
return *this;
}
static void PrettyPrinterCb (const MySmartTag *a, std::ostream &os)
{}
};
static void
myTagAPrettyPrinterCb (struct myTagA const*a, std::ostream &os)
{
//os << "struct myTagA, a="<<(uint32_t)a->a<<std::endl;
g_a = true;
}
static void
myTagBPrettyPrinterCb (struct myTagB const*b, std::ostream &os)
{
//os << "struct myTagB, b="<<b->b<<std::endl;
g_b = true;
}
static void
myTagCPrettyPrinterCb (struct myTagC const*c, std::ostream &os)
{
//os << "struct myTagC, c="<<(uint32_t)c->c[0]<<std::endl;
g_c = true;
}
static void
myTagZPrettyPrinterCb (struct myTagZ const*z, std::ostream &os)
{
//os << "struct myTagZ" << std::endl;
g_z = true;
}
static TagRegistration<struct myTagA> gMyTagARegistration ("A", &myTagAPrettyPrinterCb);
static TagRegistration<struct myTagB> gMyTagBRegistration ("B", &myTagBPrettyPrinterCb);
static TagRegistration<struct myTagC> gMyTagCRegistration ("C", &myTagCPrettyPrinterCb);
static TagRegistration<struct myTagZ> g_myTagZRegistration ("ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ",
&myTagZPrettyPrinterCb);
static TagRegistration<MySmartTag> g_myTagSmartRegistration ("SmartTag", &MySmartTag::PrettyPrinterCb);
TagsTest::TagsTest ()
: Test ("Tags")
{}
TagsTest::~TagsTest ()
{}
bool
TagsTest::RunTests (void)
{
bool ok = true;
// build initial tag.
Tags tags;
struct myTagA a;
a.a = 10;
tags.Add (a);
a.a = 0;
tags.Peek (a);
if (a.a != 10)
{
ok = false;
}
g_a = false;
tags.PrettyPrint (std::cout);
if (!g_a)
{
ok = false;
}
struct myTagB b;
b.b = 0xff;
tags.Add (b);
b.b = 0;
tags.Peek (b);
if (b.b != 0xff)
{
ok = false;
}
g_b = false;
g_a = false;
tags.PrettyPrint (std::cout);
if (!g_a || !g_b)
{
ok = false;
}
// make sure copy contains copy.
Tags other = tags;
g_b = false;
g_a = false;
other.PrettyPrint (std::cout);
if (!g_a || !g_b)
{
ok = false;
}
g_b = false;
g_a = false;
tags.PrettyPrint (std::cout);
if (!g_a || !g_b)
{
ok = false;
}
struct myTagA oA;
oA.a = 0;
other.Peek (oA);
if (oA.a != 10)
{
ok = false;
}
struct myTagB oB;
oB.b = 1;
other.Peek (oB);
if (oB.b != 0xff)
{
ok = false;
}
// remove data.
other.Remove (oA);
if (other.Peek (oA))
{
ok = false;
}
g_b = false;
g_a = false;
other.PrettyPrint (std::cout);
if (g_a || !g_b)
{
ok = false;
}
if (!tags.Peek (oA))
{
ok = false;
}
other.Remove (oB);
if (other.Peek (oB))
{
ok = false;
}
if (!tags.Peek (oB))
{
ok = false;
}
other = tags;
Tags another = other;
struct myTagC c;
memset (c.c, 0x66, 16);
another.Add (c);
c.c[0] = 0;
another.Peek (c);
if (!another.Peek (c))
{
ok = false;
}
if (tags.Peek (c))
{
ok = false;
}
other = other;
//other.prettyPrint (std::cout);
//struct myInvalidTag invalid;
//tags.add (&invalid);
struct myTagZ tagZ;
Tags testLastTag;
tagZ.z = 0;
testLastTag.Add (tagZ);
g_z = false;
testLastTag.PrettyPrint (std::cout);
if (!g_z)
{
ok = false;
}
MySmartTag smartTag;
{
Tags tmp;
tmp.Add (smartTag);
tmp.Peek (smartTag);
tmp.Remove (smartTag);
}
return ok;
}
static TagsTest gTagsTest;
}; // namespace ns3
#endif /* RUN_SELF_TESTS */
+336
View File
@@ -0,0 +1,336 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2006 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef TAGS_H
#define TAGS_H
#include <stdint.h>
#include <ostream>
#include <vector>
namespace ns3 {
template <typename T>
class TagPrettyPrinter;
/**
* \ingroup constants
* \brief Tag maximum size
* The maximum size (in bytes) of a Tag is stored
* in this constant.
*/
#define TAGS_MAX_SIZE 16
class Tags {
public:
inline Tags ();
inline Tags (Tags const &o);
inline Tags &operator = (Tags const &o);
inline ~Tags ();
template <typename T>
void Add (T const&tag);
template <typename T>
bool Remove (T &tag);
template <typename T>
bool Peek (T &tag) const;
void PrettyPrint (std::ostream &os);
inline void RemoveAll (void);
enum {
SIZE = TAGS_MAX_SIZE
};
private:
struct TagData {
uint8_t m_data[Tags::SIZE];
struct TagData *m_next;
uint32_t m_id;
uint32_t m_count;
};
bool Remove (uint32_t id);
struct Tags::TagData *AllocData (void);
void FreeData (struct TagData *data);
static struct Tags::TagData *gFree;
static uint32_t gN_free;
struct TagData *m_next;
};
/**
* \brief pretty print packet tags
*
* This class is used to register a pretty-printer
* callback function to print in a nice user-friendly
* way the content of the target type. To register
* such a type, all you need to do is instantiate
* an instance of this type as a static variable.
*/
template <typename T>
class TagRegistration {
public:
/**
* \param uuid a uuid generated with uuidgen
* \param fn a function which can pretty-print an instance
* of type T in the output stream.
*/
TagRegistration<T> (std::string uuid, void(*fn) (T const*, std::ostream &));
private:
static void PrettyPrinterCb (uint8_t *buf, std::ostream &os);
static void DestructorCb (uint8_t *buf);
static void(*m_prettyPrinter) (T const*, std::ostream &);
};
}; // namespace ns3
/**************************************************************
An implementation of the templates defined above
*************************************************************/
#include "ns3/assert.h"
#include <string>
namespace ns3 {
class TagRegistry {
public:
typedef void (*PrettyPrinter) (uint8_t [Tags::SIZE], std::ostream &);
typedef void (*Destructor) (uint8_t [Tags::SIZE]);
void Record (std::string uuid, PrettyPrinter prettyPrinter, Destructor destructor);
/**
* returns a numeric integer which uniquely identifies the input string.
* that integer cannot be zero which is a reserved value.
*/
uint32_t LookupUid (std::string uuid);
void PrettyPrint (uint32_t uid, uint8_t buf[Tags::SIZE], std::ostream &os);
void Destruct (uint32_t uid, uint8_t buf[Tags::SIZE]);
static TagRegistry *GetInstance (void);
private:
TagRegistry ();
struct TagInfoItem
{
std::string uuid;
PrettyPrinter printer;
Destructor destructor;
};
typedef std::vector<struct TagInfoItem> TagsData;
typedef std::vector<struct TagInfoItem>::const_iterator TagsDataCI;
static bool CompareItem (const struct TagInfoItem &a, const struct TagInfoItem &b);
bool m_sorted;
TagsData m_registry;
};
/**
* The TypeUid class is used to create a mapping Type --> uid
* Note that we use a static getUuid function which contains a
* static std::string variable rather than a simpler static
* member std::string variable to ensure the proper order
* of initialization when these methods are invoked
* from the constructor of another static variable.
*/
template <typename T>
class TypeUid {
public:
static void Record (std::string uuid);
static const uint32_t GetUid (void);
private:
static std::string *GetUuid (void);
T m_realType;
};
template <typename T>
void TypeUid<T>::Record (std::string uuid)
{
*(GetUuid ()) = uuid;
}
template <typename T>
const uint32_t TypeUid<T>::GetUid (void)
{
static const uint32_t uid = TagRegistry::GetInstance ()->
LookupUid (*(GetUuid ()));
return uid;
}
template <typename T>
std::string *TypeUid<T>::GetUuid (void)
{
static std::string uuid;
return &uuid;
}
/**
* Implementation of the TagRegistration registration class.
* It records a callback with the TagRegistry
* This callback performs type conversion before forwarding
* the call to the user-provided function.
*/
template <typename T>
TagRegistration<T>::TagRegistration (std::string uuid, void (*prettyPrinter) (T const*, std::ostream &))
{
NS_ASSERT (sizeof (T) <= Tags::SIZE);
m_prettyPrinter = prettyPrinter;
TagRegistry::GetInstance ()->
Record (uuid, &TagRegistration<T>::PrettyPrinterCb, &TagRegistration<T>::DestructorCb);
TypeUid<T>::Record (uuid);
}
template <typename T>
void
TagRegistration<T>::PrettyPrinterCb (uint8_t *buf, std::ostream &os)
{
NS_ASSERT (sizeof (T) <= Tags::SIZE);
T *tag = reinterpret_cast<T *> (buf);
(*m_prettyPrinter) (tag, os);
}
template <typename T>
void
TagRegistration<T>::DestructorCb (uint8_t *buf)
{
T *tag = reinterpret_cast<T *> (buf);
tag->~T ();
}
template <typename T>
void (*TagRegistration<T>::m_prettyPrinter) (T const*, std::ostream &) = 0;
template <typename T>
void
Tags::Add (T const&tag)
{
NS_ASSERT (sizeof (T) <= Tags::SIZE);
// ensure this id was not yet added
for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next)
{
NS_ASSERT (cur->m_id != TypeUid<T>::GetUid ());
}
struct TagData *newStart = AllocData ();
newStart->m_count = 1;
newStart->m_next = 0;
newStart->m_id = TypeUid<T>::GetUid ();
void *buf = &newStart->m_data;
new (buf) T (tag);
newStart->m_next = m_next;
m_next = newStart;
}
template <typename T>
bool
Tags::Remove (T &tag)
{
NS_ASSERT (sizeof (T) <= Tags::SIZE);
return Remove (TypeUid<T>::GetUid ());
}
template <typename T>
bool
Tags::Peek (T &tag) const
{
NS_ASSERT (sizeof (T) <= Tags::SIZE);
for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next)
{
if (cur->m_id == TypeUid<T>::GetUid ())
{
/* found tag */
T *data = reinterpret_cast<T *> (&cur->m_data);
tag = T (*data);
return true;
}
}
/* no tag found */
return false;
}
Tags::Tags ()
: m_next ()
{}
Tags::Tags (Tags const &o)
: m_next (o.m_next)
{
if (m_next != 0)
{
m_next->m_count++;
}
}
Tags &
Tags::operator = (Tags const &o)
{
// self assignment
if (m_next == o.m_next)
{
return *this;
}
RemoveAll ();
m_next = o.m_next;
if (m_next != 0)
{
m_next->m_count++;
}
return *this;
}
Tags::~Tags ()
{
RemoveAll ();
}
void
Tags::RemoveAll (void)
{
struct TagData *prev = 0;
for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next)
{
cur->m_count--;
if (cur->m_count > 0)
{
break;
}
if (prev != 0)
{
TagRegistry::GetInstance ()->
Destruct (prev->m_id, prev->m_data);
FreeData (prev);
}
prev = cur;
}
if (prev != 0)
{
TagRegistry::GetInstance ()->
Destruct (prev->m_id, prev->m_data);
FreeData (prev);
}
m_next = 0;
}
}; // namespace ns3
#endif /* TAGS_H */
+66
View File
@@ -0,0 +1,66 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef TERMINAL_TRACE_RESOLVER_H
#define TERMINAL_TRACE_RESOLVER_H
#include "trace-resolver.h"
namespace ns3 {
class TraceContext;
template <typename T>
class TerminalTraceResolver : public TraceResolver
{
public:
TerminalTraceResolver (T &traceSource, TraceContext const &context);
private:
virtual void DoConnect (CallbackBase const &cb);
virtual void DoDisconnect (CallbackBase const &cb);
T &m_traceSource;
};
}//namespace ns3
namespace ns3 {
template <typename T>
TerminalTraceResolver<T>::TerminalTraceResolver (T &traceSource,
TraceContext const &context)
: TraceResolver (context),
m_traceSource (traceSource)
{}
template <typename T>
void
TerminalTraceResolver<T>::DoConnect (CallbackBase const &cb)
{
m_traceSource.AddCallback (cb, GetContext ());
}
template <typename T>
void
TerminalTraceResolver<T>::DoDisconnect (CallbackBase const &cb)
{
m_traceSource.RemoveCallback (cb);
}
}//namespace ns3
#endif /* TERMINAL_TRACE_RESOLVER_H */
+320
View File
@@ -0,0 +1,320 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "trace-context.h"
#include "ns3/assert.h"
namespace ns3 {
std::vector<uint8_t> TraceContext::m_sizes;
TraceContext::TraceContext ()
: m_data (0)
{}
TraceContext::TraceContext (TraceContext const &o)
: m_data (o.m_data)
{
if (m_data != 0)
{
m_data->count++;
}
}
TraceContext const &
TraceContext::operator = (TraceContext const &o)
{
if (m_data != 0)
{
m_data->count--;
if (m_data->count == 0)
{
uint8_t *buffer = (uint8_t *)m_data;
delete [] buffer;
}
}
m_data = o.m_data;
if (m_data != 0)
{
m_data->count++;
}
return *this;
}
TraceContext::~TraceContext ()
{
if (m_data != 0)
{
m_data->count--;
if (m_data->count == 0)
{
uint8_t *buffer = (uint8_t *)m_data;
delete [] buffer;
}
}
}
uint8_t
TraceContext::GetSize (uint8_t uid)
{
return m_sizes[uid];
}
void
TraceContext::Add (TraceContext const &o)
{
if (o.m_data == 0)
{
return;
}
uint8_t currentUid;
uint16_t i = 0;
while (i < o.m_data->size)
{
currentUid = o.m_data->data[i];
uint8_t size = TraceContext::GetSize (currentUid);
uint8_t *selfBuffer = CheckPresent (currentUid);
uint8_t *otherBuffer = &(o.m_data->data[i+1]);
if (selfBuffer != 0)
{
if (memcmp (selfBuffer, otherBuffer, size) != 0)
{
NS_FATAL_ERROR ("You cannot add TraceContexts which "<<
"have different values stored in them.");
}
}
else
{
DoAdd (currentUid, otherBuffer);
}
i += 1 + size;
}
}
uint8_t *
TraceContext::CheckPresent (uint8_t uid) const
{
if (m_data == 0)
{
return false;
}
uint8_t currentUid;
uint16_t i = 0;
do {
currentUid = m_data->data[i];
uint8_t size = TraceContext::GetSize (currentUid);
if (currentUid == uid)
{
return &m_data->data[i+1];
}
i += 1 + size;
} while (i < m_data->size && currentUid != 0);
return 0;
}
bool
TraceContext::DoAdd (uint8_t uid, uint8_t const *buffer)
{
NS_ASSERT (uid != 0);
uint8_t size = TraceContext::GetSize (uid);
uint8_t *present = CheckPresent (uid);
if (present != 0) {
if (memcmp (present, buffer, size) == 0)
{
return true;
}
else
{
return false;
}
}
if (m_data == 0)
{
uint16_t newSize = 1 + size;
uint16_t allocatedSize;
if (newSize > 4)
{
allocatedSize = sizeof (struct Data) + newSize - 4;
}
else
{
allocatedSize = sizeof (struct Data);
}
struct Data *data = (struct Data *) (new uint8_t [allocatedSize] ());
data->size = newSize;
data->count = 1;
data->data[0] = uid;
memcpy (data->data + 1, buffer, size);
m_data = data;
}
else
{
uint16_t newSize = m_data->size + 1 + size;
uint16_t allocatedSize;
if (newSize > 4)
{
allocatedSize = sizeof (struct Data) + newSize - 4;
}
else
{
allocatedSize = sizeof (struct Data);
}
struct Data *data = (struct Data *) (new uint8_t [allocatedSize] ());
data->size = newSize;
data->count = 1;
memcpy (data->data, m_data->data, m_data->size);
data->data[m_data->size] = uid;
memcpy (data->data + m_data->size + 1, buffer, size);
m_data->count--;
if (m_data->count == 0)
{
uint8_t *buffer = (uint8_t *)m_data;
delete [] buffer;
}
m_data = data;
}
return true;
}
bool
TraceContext::DoGet (uint8_t uid, uint8_t *buffer) const
{
if (m_data == 0)
{
return false;
}
uint8_t currentUid;
uint16_t i = 0;
do {
currentUid = m_data->data[i];
uint8_t size = TraceContext::GetSize (currentUid);
if (currentUid == uid)
{
memcpy (buffer, &m_data->data[i+1], size);
return true;
}
i += 1 + size;
} while (i < m_data->size && currentUid != 0);
return false;
}
uint8_t
TraceContext::DoGetNextUid (void)
{
static uint8_t uid = 0;
if (uid == 0)
{
m_sizes.push_back (0);
}
uid++;
return uid;
}
}//namespace ns3
#include "ns3/test.h"
namespace ns3 {
template <int N>
class Ctx
{
public:
Ctx () : m_v (0) {}
Ctx (int v) : m_v (v) {}
int Get (void) const { return N;}
private:
int m_v;
};
class TraceContextTest : public Test
{
public:
TraceContextTest ();
virtual bool RunTests (void);
};
TraceContextTest::TraceContextTest ()
: Test ("TraceContext")
{}
bool
TraceContextTest::RunTests (void)
{
bool ok = true;
TraceContext ctx;
Ctx<0> v0;
Ctx<0> v01 = Ctx<0> (1);
Ctx<1> v1;
Ctx<2> v2;
Ctx<3> v3;
if (ctx.SafeGet (v0))
{
ok = false;
}
ctx.Add (v0);
ctx.Add (v0);
if (ctx.SafeAdd (v01))
{
ok = false;
}
ctx.Get (v0);
ctx.Add (v1);
ctx.Get (v1);
ctx.Get (v0);
ctx.Get (v1);
TraceContext copy = ctx;
ctx.Get (v0);
ctx.Get (v1);
copy.Get (v0);
copy.Get (v1);
copy.Add (v2);
copy.Get (v0);
copy.Get (v1);
copy.Get (v2);
ctx.Add (v3);
ctx.Get (v0);
ctx.Get (v1);
ctx.Get (v3);
if (ctx.SafeGet (v2))
{
ok = false;
}
if (copy.SafeGet (v3))
{
ok = false;
}
ctx.Add (copy);
ctx.Get (v2);
if (copy.SafeGet (v3))
{
ok = false;
}
copy.Add (ctx);
copy.Get (v3);
return ok;
}
static TraceContextTest g_traceContextTest;
}//namespace ns3
+167
View File
@@ -0,0 +1,167 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef TRACE_CONTEXT_H
#define TRACE_CONTEXT_H
#include <stdint.h>
#include <vector>
#include "ns3/fatal-error.h"
namespace ns3 {
/**
* \brief Provide context to trace sources
* \ingroup lowleveltracing
*
* Instances of this class are used to hold context
* for each trace source. Each instance holds a list of
* 'contexts'. Trace sinks can lookup these contexts
* from this list with the ns3::TraceContext::Get method.
*
* This class is implemented
* using Copy On Write which means that copying unmodified
* versions of this class is very cheap. However, modifying
* the content of this class through a call
* to ns3::TraceContext::Add will trigger a costly memory
* reallocation if needed.
*/
class TraceContext
{
public:
TraceContext ();
TraceContext (TraceContext const &o);
TraceContext const & operator = (TraceContext const &o);
~TraceContext ();
/**
* \param context add context to list of trace contexts.
*/
template <typename T>
void Add (T const &context);
/**
* \param o the other context
*
* Perform the Union operation (in the sense of set theory) on the
* two input lists of elements. This method is used in the
* ns3::CallbackTraceSourceSource class when multiple sinks are connected
* to a single source to ensure that the source does not need
* to store a single TraceContext instance per connected sink.
* Instead, all sinks share the same TraceContext.
*/
void Add (TraceContext const &o);
/**
* \param context context to get from this list of trace contexts.
*
* This method cannot fail. If the requested trace context is not
* stored in this TraceContext, then, the program will halt.
*/
template <typename T>
void Get (T &context) const;
private:
friend class TraceContextTest;
// used exclusively for testing code.
template <typename T>
bool SafeGet (T &context) const;
template <typename T>
bool SafeAdd (T &context);
template <typename T>
static uint8_t GetUid (void);
template <typename T>
static uint8_t GetNextUid (void);
static uint8_t DoGetNextUid (void);
static uint8_t GetSize (uint8_t uid);
uint8_t *CheckPresent (uint8_t uid) const;
bool DoAdd (uint8_t uid, uint8_t const *buffer);
bool DoGet (uint8_t uid, uint8_t *buffer) const;
static std::vector<uint8_t> m_sizes;
struct Data {
uint16_t count;
uint16_t size;
uint8_t data[4];
} * m_data;
};
}//namespace ns3
namespace ns3 {
template <typename T>
void
TraceContext::Add (T const &context)
{
uint8_t *data = (uint8_t *) &context;
bool ok = DoAdd (TraceContext::GetUid<T> (), data);
if (!ok)
{
NS_FATAL_ERROR ("Trying to add twice the same type with different values is invalid.");
}
}
template <typename T>
void
TraceContext::Get (T &context) const
{
uint8_t *data = (uint8_t *) &context;
bool found = DoGet (TraceContext::GetUid<T> (), data);
if (!found)
{
NS_FATAL_ERROR ("Type not stored in TraceContext");
}
}
template <typename T>
bool
TraceContext::SafeGet (T &context) const
{
uint8_t *data = (uint8_t *) &context;
bool found = DoGet (TraceContext::GetUid<T> (), data);
return found;
}
template <typename T>
bool
TraceContext::SafeAdd (T &context)
{
uint8_t *data = (uint8_t *) &context;
bool ok = DoAdd (TraceContext::GetUid<T> (), data);
return ok;
}
template <typename T>
uint8_t
TraceContext::GetUid (void)
{
static uint8_t uid = GetNextUid<T> ();
return uid;
}
template <typename T>
uint8_t
TraceContext::GetNextUid (void)
{
uint8_t uid = DoGetNextUid ();
m_sizes.push_back (sizeof (T));
return uid;
}
}//namespace ns3
#endif /* TRACE_CONTEXT_H */
+104
View File
@@ -0,0 +1,104 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "trace-resolver.h"
namespace ns3 {
TraceResolver::TraceResolver (TraceContext const &context)
: m_context (context)
{}
TraceResolver::~TraceResolver ()
{}
TraceContext const &
TraceResolver::GetContext (void) const
{
return m_context;
}
void
TraceResolver::Connect (std::string path, CallbackBase const &cb)
{
std::string::size_type cur = 1;
// check that first char is "/"
std::string::size_type next = path.find ("/", cur);
std::string element = std::string (path, cur, next-1);
TraceResolverList resolverList = DoLookup (element);
for (TraceResolverList::iterator i = resolverList.begin (); i != resolverList.end (); i++)
{
TraceResolver *resolver = *i;
if (next == std::string::npos)
{
// we really break the recursion here.
resolver->DoConnect (cb);
}
else
{
std::string subpath = std::string (path, next, std::string::npos);
resolver->Connect (subpath, cb);
}
delete resolver;
}
resolverList.erase (resolverList.begin (), resolverList.end ());
}
void
TraceResolver::Disconnect (std::string path, CallbackBase const &cb)
{
std::string::size_type cur = 1;
// check that first char is "/"
std::string::size_type next = path.find ("/", cur);
std::string element = std::string (path, cur, next-1);
TraceResolverList resolverList = DoLookup (element);
for (TraceResolverList::iterator i = resolverList.begin (); i != resolverList.end (); i++)
{
TraceResolver *resolver = *i;
if (next == std::string::npos)
{
// we really break the recursion here.
resolver->DoDisconnect (cb);
}
else
{
std::string subpath = std::string (path, next, std::string::npos);
resolver->Disconnect (subpath, cb);
}
delete resolver;
}
resolverList.erase (resolverList.begin (), resolverList.end ());
}
TraceResolver::TraceResolverList
TraceResolver::DoLookup (std::string id) const
{
return TraceResolverList ();
}
void
TraceResolver::DoConnect (CallbackBase const &cb)
{}
void
TraceResolver::DoDisconnect (CallbackBase const &cb)
{}
}//namespace ns3
+119
View File
@@ -0,0 +1,119 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef TRACE_RESOLVER_H
#define TRACE_RESOLVER_H
#include <string>
#include <list>
#include "trace-context.h"
namespace ns3 {
class CallbackBase;
/**
* \brief the base class which is used to incremental perform trace
* namespace resolution.
* \ingroup lowleveltracing
*
* This class provides a public API to the ns3::TraceRoot object:
* - ns3::TraceResolver::Connect
* - ns3::TraceResolver::Disconnect
*
* It also provides an API for its subclasses. Each subclass should
* implement one of:
* - ns3::TraceResolver::DoLookup
* - ns3::TraceResolver::DoConnect and ns3::TraceResolver::DoDisconnect
* Each subclass must also provide an ns3::TraceContext to the TraceResolver
* constructor. Finally, each subclass can access the ns3::TraceContext
* associated to this ns3::TraceResolver through the
* ns3::TraceResolver::GetContext method.
*/
class TraceResolver
{
public:
virtual ~TraceResolver ();
/**
* \param path the namespace path to resolver
* \param cb the callback to connect to the matching namespace
*
* This method is typically invoked by ns3::TraceRoot but advanced
* users could also conceivably call it directly if they want to
* skip the ns3::TraceRoot.
*/
void Connect (std::string path, CallbackBase const &cb);
/**
* \param path the namespace path to resolver
* \param cb the callback to disconnect in the matching namespace
*
* This method is typically invoked by ns3::TraceRoot but advanced
* users could also conceivably call it directly if they want to
* skip the ns3::TraceRoot.
*/
void Disconnect (std::string path, CallbackBase const &cb);
protected:
/**
* \param context the context used to initialize this TraceResolver.
*
* Every subclass must call this constructor
*/
TraceResolver (TraceContext const &context);
/**
* \returns the ns3::TraceContext stored in this ns3::TraceResolver.
*
* Subclasses usually invoke this method to get access to the
* TraceContext stored here to pass it down to the TraceResolver
* constructors invoked from within the DoLookup method.
*/
TraceContext const &GetContext (void) const;
typedef std::list<TraceResolver *> TraceResolverList;
private:
TraceResolver ();
/**
* \param id the id to resolve. This is supposed to be
* one element of the global tracing namespace.
* \returns a list of reslvers which match the input namespace element
*
* A subclass which overrides this method should return a potentially
* empty list of pointers to ns3::TraceResolver instances which match
* the input namespace element. Each of these TraceResolver should be
* instanciated with a TraceContext which holds enough context
* information to identify the type of the TraceResolver.
*/
virtual TraceResolverList DoLookup (std::string id) const;
/**
* \param cb callback to connect
*
* This method is invoked on leaf trace resolvers.
*/
virtual void DoConnect (CallbackBase const &cb);
/**
* \param cb callback to disconnect
*
* This method is invoked on leaf trace resolvers.
*/
virtual void DoDisconnect (CallbackBase const &cb);
TraceContext m_context;
};
}//namespace ns3
#endif /* TRACE_RESOLVER_H */
+54
View File
@@ -0,0 +1,54 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "trace-root.h"
#include "ns3/composite-trace-resolver.h"
#include "ns3/trace-context.h"
namespace ns3 {
void
TraceRoot::Connect (std::string path, CallbackBase const &cb)
{
TraceResolver *resolver = GetComposite ();
resolver->Connect (path, cb);
}
void
TraceRoot::Disconnect (std::string path, CallbackBase const &cb)
{
TraceResolver *resolver = GetComposite ();
resolver->Disconnect (path, cb);
}
void
TraceRoot::Register (std::string name,
Callback<TraceResolver *,TraceContext const &> createResolver)
{
CompositeTraceResolver *resolver = GetComposite ();
resolver->Add (name, createResolver, TraceRoot::NOTHING);
}
CompositeTraceResolver *
TraceRoot::GetComposite (void)
{
static CompositeTraceResolver resolver = CompositeTraceResolver (TraceContext ());
return &resolver;
}
} // namespace ns3
+338
View File
@@ -0,0 +1,338 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef TRACE_ROOT_H
#define TRACE_ROOT_H
#include <string>
#include "ns3/callback.h"
/**
* \defgroup lowleveltracing Low-level tracing
*
* This low-level API is built around a few concepts:
* - There can be any number of trace source objects. Each trace source
* object can generate any number of trace events. The current
* trace source objects are: ns3::CallbackTraceSourceSource, ns3::UVTraceSource,
* ns3::SVTraceSource, and, ns3::FVTraceSource.
* - Each trace source can be connected to any number of trace sinks.
* A trace sink is a ns3::Callback with a very special signature. Its
* first argument is always a ns3::TraceContext.
* - Every trace source is uniquely identified by a ns3::TraceContext. Every
* trace sink can query a ns3::TraceContext for information. This allows
* a trace sink which is connected to multiple trace sources to identify
* from which source each event is coming from.
*
* To define new trace sources, a model author needs to instante one trace source
* object for each kind of tracing event he wants to export. The trace source objects
* currently defined are:
* - ns3::CallbackTraceSourceSource: this trace source can be used to convey any kind of
* trace event to the user. It is a functor, that is, it is a variable
* which behaves like a function which will forward every event to every
* connected trace sink (i.e., ns3::Callback). This trace source takes
* up to four arguments and forwards these 4 arguments together with the
* ns3::TraceContext which identifies this trace source to the connected
* trace sinks.
* - ns3::UVTraceSource: this trace source is used to convey key state variable
* changes to the user. It behaves like a normal integer unsigned variable:
* you can apply every normal arithmetic operator to it. It will forward
* every change in the value of the variable back to every connected trace
* sink by providing a TraceContext, the old value and the new value.
* - ns3::SVTraceSource: this is the signed integer equivalent of
* ns3::UVTraceSource.
* - ns3::FVTraceSource: this is the floating point equivalent of
* ns3::UVTraceSource and ns3::SVTraceSource.
*
* For example, to define a trace source which notifies you of a new packet
* being transmitted, you would have to:
* \code
* class MyModel
* {
* public:
* void Tx (Packet const &p);
* private:
* CallbackTraceSource<Packet const &> m_txTrace;
* };
*
* void
* MyModel::Tx (Packet const &p)
* {
* // trace packet tx event.
* m_txTrace (p);
* // ... send the packet for real.
* }
* \endcode
*
* Once the model author has instantiated these objects and has wired them
* in his simulation code (that is, he calls them wherever he wants to trigger
* a trace event), he needs to make these trace sources available to users
* to allow them to connect any number of trace sources to any number
* of user trace sinks. While it would be possible to make each model
* export directly each of his trace source instances and request users to
* invoke a source->Connect (callback) method to perform the connection
* explicitely, it was felt that this was a bit cumbersome to do.
*
* As such, the ``connection'' between a set of sources and a sink is
* performed through a third-party class, the TraceResolver, which
* can be used to automate the connection of multiple matching trace sources
* to a single sink. This TraceResolver works by defining a hierarchical
* tracing namespace: the root of this namespace is accessed through the
* ns3::TraceRoot class. The namespace is represented as a string made of
* multiple elements, each of which is separated from the other elements
* by the '/' character. A namespace string always starts with a '/'.
*
* By default, the current simulation models provide a '/nodes' tracing root.
* This '/nodes' namespace is structured as follows:
* \code
* /nodes/n/arp
* /nodes/n/udp
* /nodes/n/ipv4
* /tx
* /rx
* /drop
* /interfaces/n/netdevice
* /queue/
* /enque
* /deque
* /drop
* \endcode
*
* The 'n' element which follows the /nodes and /interfaces namespace elements
* identify a specific node and interface through their index within the
* ns3::NodeList and ns3::Ipv4 objects respectively.
*
* To connect a trace sink to a trace source identified by a namespace string,
* a user can call the ns3::TraceRoot::Connect method (the ns3::TraceRoot::Disconnect
* method does the symmetric operation). This connection method can accept
* fully-detailed namespace strings but it can also perform pattern matching
* on the user-provided namespace strings to connect multiple trace sources
* to a single trace sink in a single connection operation.
*
* The syntax of the pattern matching rules are loosely based on regular
* expressions:
* - the '*' character matches every element
* - the (a|b) construct matches element 'a' or 'b'
* - the [ss-ee] construct matches all numerical values which belong
* to the interval which includes ss and ee
*
* For example, the user could use the following to connect a single sink
* to the ipv4 tx, rx, and drop trace events:
*
* \code
* void MyTraceSink (TraceContext const &context, Packet &packet);
* TraceRoot::Connect ("/nodes/ * /ipv4/ *", MakeCallback (&MyTraceSink));
* \endcode
*
* Of course, this code would work only if the signature of the trace sink
* is exactly equal to the signature of all the trace sources which match
* the namespace string (if one of the matching trace source does not match
* exactly, a fatal error will be triggered at runtime during the connection
* process). The ns3::TraceContext extra argument contains
* information on where the trace source is located in the namespace tree.
* In that example, if there are multiple nodes in this scenario, each
* call to the MyTraceSink function would receive a different TraceContext,
* each of which would contain a different NodeList::Index object.
*
* It is important to understand exactly what an ns3::TraceContext
* is. It is a container for a number of type instances. Each instance of
* a ns3::TraceContext contains one and only one instance of a given type.
* ns3::TraceContext::Add can be called to add a type instance into a
* TraceContext instance and ns3::TraceContext::Get can be called to get
* a copy of a type instance stored into the ns3::TraceContext. If ::Get
* cannot retrieve the requested type, a fatal error is triggered at
* runtime. The values stored into an ns3::TraceContext attached to a
* trace source are automatically determined during the namespace
* resolution process. To retrieve a value from a ns3::TraceContext, the
* code can be as simple as this:
* \code
* void MyTraceSink (TraceContext const &context, Packet &packet)
* {
* NodeList::Index index;
* context.Get (index);
* std::cout << "node id=" << NodeList::GetNode (index)->GetId () << std::endl;
* }
* \endcode
*
* The hierarchical global namespace described here is not implemented
* in a single central location: it was felt that doing this would make
* it too hard to introduce user-specific models which could hook
* automatically into the overal tracing system. If the tracing
* namespace was implemented in a single central location, every model
* author would have had to modify this central component to make
* his own model available to trace users.
*
* Instead, the handling of the namespace is distributed across every relevant
* model: every model implements only the part of the namespace it is
* really responsible for. To do this, every model is expected
* to provide an instance of a TraceResolver whose
* responsability is to recursively provide access to the trace sources
* defined in its model. Each TraceResolver instance should be a subclass
* of the TraceResolver base class which implements either the DoLookup
* or the DoConnect and DoDisconnect methods. Because implementing these
* methods can be a bit tedious, our tracing framework provides a number
* of helper template classes which should save the model author from
* having to implement his own in most cases:
* - ns3::CompositeTraceResolver: this subclass of ns3::TraceResolver can
* be used to aggregate together multiple trace sources and multiple other
* ns3::TraceResolver instances.
* - ns3::ArrayTraceResolver: this subclass of ns3::TraceResolver can be
* used to match any number of elements within an array where every element
* is identified by its index.
*
* Once you can instantiate your own ns3::TraceResolver object instance, you
* have to hook it up into the global namespace. There are two ways to do this:
* - you can hook your ns3::TraceResolver creation method as a new trace
* root by using the ns3::TraceRoot::Register method
* - you can hook your new ns3::TraceResolver creation method into the
* container of your model. This step will obvsiouly depend on which model
* contains your own model but, if you wrote a new l3 protocol, all you
* would have to do to hook into your container L3Demux class is to implement
* the pure virtual method inherited from the L3Protocol class whose name is
* ns3::L3protocol::CreateTraceResolver.
*
* So, in most cases, exporting a model's trace sources is a matter of
* implementing a method CreateTraceResolver as shown below:
* \code
* class MyModel
* {
* public:
* enum TraceType {
* TX,
* RX,
* ...
* };
* TraceResolver *CreateTraceResolver (TraceContext const &context);
* void Tx (Packet const &p);
* private:
* CallbackTraceSource<Packet const &> m_txTrace;
* };
*
* TraceResolver *
* MyModel::CreateTraceResolver (TraceContext const &context)
* {
* CompositeTraceResolver *resolver = new CompositeTraceResolver (context);
* resolver->Add ("tx", m_txTrace, MyModel::TX);
* return resolver;
* }
* void
* MyModel::Tx (Packet const &p)
* {
* m_txTrace (p);
* }
* \endcode
*
* If you really want to have fun and implement your own ns3::TraceResolver
* subclass, you need to understand the basic Connection and Disconnection
* algorithm. The code of that algorithm is wholy contained in the
* ns3::TraceResolver::Connect and ns3::TraceResolver::Disconnect methods.
* The idea is that we recursively parse the input namespace string by removing
* the first namespace element. This element is 'resolved' is calling
* the ns3::TraceResolver::DoLookup method which returns a list of
* TraceResolver instances. Each of the returned TraceResolver instance is
* then given what is left of the namespace by calling ns3::TraceResolver::Connect
* until the last namespace element is processed. At this point, we invoke
* the ns3::TraceResolver::DoConnect or ns3::TraceResolver::DoDisconnect
* methods to break the recursion. A good way to understand this algorithm
* is to trace its behavior. Let's say that you want to connect to
* '/nodes/ * /ipv4/interfaces/ * /netdevice/queue/ *'. It would generate
* the following call traces:
*
* \code
* TraceRoot::Connect ("/nodes/ * /ipv4/interfaces/ * /netdevice/queue/ *", callback);
* traceContext = TraceContext ();
* rootResolver = CompositeTraceResolver (traceContext);
* rootResolver->Connect ("/nodes/ * /ipv4/interfaces/ * /netdevice/queue/ *", callback);
* resolver = CompositeTraceResolver::DoLookup ("nodes");
* return NodeList::CreateTraceResolver (GetContext ());
* return ArrayTraceResolver (context);
* resolver->Connect ("/ * /ipv4/interfaces/ * /netdevice/queue/ *", callback);
* ArrayTraceResolver::DoLookup ("*");
* for (i = 0; i < n_nodes; i++)
* resolver = nodes[i]->CreateTraceResolver (GetContext ());
* return CompositeTraceResolver (context);
* resolvers.add (resolver);
* return resolvers;
* for resolver in (resolvers)
* resolver->Connect ("/ipv4/interfaces/ * /netdevice/queue/ *", callback);
* CompositeTraceResolver::DoLookup ("ipv4");
* resolver = ipv4->CreateTraceResolver (GetContext ());
* return CompositeTraceResolver (context);
* return resolver;
* resolver->Connect ("/interfaces/ * /netdevice/queue/ *", callback);
* CompositeTraceResolver::DoLookup ("interfaces");
* resolver = ArrayTraceResolver (GetContext ());
* resolver->Connect ("/ * /netdevice/queue/ *", callback);
* ArrayTraceResolver::DoLookup ("*");
* for (i = 0; i < n_interfaces; i++)
* resolver = interfaces[i]->CreateTraceResolver (GetContext ());
* return CompositeTraceResolver ()
* resolvers.add (resolver);
* return resolvers;
* resolver->Connect ("/netdevice/queue/ *", callback);
* CompositeTraceResolver::DoLookup ("netdevice");
* resolver = NetDevice::CreateTraceResolver (GetContext ());
* return CompositeTraceResolver ();
* return resolver;
* resolver->Connect ("/queue/ *", callback);
* CompositeTraceResolver::DoLookup ("queue");
* resolver = Queue::CreateTraceResolver (GetContext ());
* return CompositeTraceResolver ();
* return resolver
* resolver->Connect ("*", callback);
* CompositeTraceResolver::DoLookup ("*");
* for match in (matches)
* resolver = TerminalTraceResolver ("match");
* resolvers.add (resolver)
* return resolvers;
* for resolver in (resolvers)
* TerminalTraceResolver->DoConnect (callback);
* \endcode
*/
namespace ns3 {
class CompositeTraceResolver;
class TraceResolver;
class TraceContext;
class CallbackBase;
/**
* \brief The main class used to access tracing functionality for
* a user.
*
* \ingroup lowleveltracing
*/
class TraceRoot
{
public:
static void Connect (std::string path, CallbackBase const &cb);
static void Disconnect (std::string path, CallbackBase const &cb);
static void Register (std::string name,
Callback<TraceResolver *,TraceContext const &> createResolver);
private:
static CompositeTraceResolver *GetComposite (void);
enum TraceType {
NOTHING,
};
};
}// namespace ns3
#endif /* TRACE_ROOT_H */
+29
View File
@@ -0,0 +1,29 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2005 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "trailer.h"
namespace ns3 {
Trailer::~Trailer ()
{}
}; // namespace ns3
+127
View File
@@ -0,0 +1,127 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2005 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef TRAILER_H
#define TRAILER_H
#include "chunk.h"
namespace ns3 {
/**
* \brief Protocol trailer serialization and deserialization.
*
* Every Protocol trailer which needs to be inserted or removed
* from a Packet instance must derive from this abstract base class
* and implement the private pure virtual methods listed below:
* - ns3::Trailer::SerializeTo
* - ns3::Trailer::DeserializeFrom
* - ns3::Trailer::GetSerializedSize
* - ns3::Trailer::PrintTo
*
* Note that the SerializeTo and DeserializeFrom methods behave
* in a way which might seem surprising to users: the input iterator
* really points to the end of the buffer to which and from which
* the user is expected to write and read respectively. This means that
* if the trailer has a fixed size and if the user wishes to read or
* write that trailer from front to back, the user must rewind the
* iterator by hand to go to the start of the trailer. Typical code
* looks like this:
* \code
* void CrcTrailer::SerializeTo (Buffer::Iterator end)
* {
* end.Prev (4);
* end.WriteHtonU32 (m_crc);
* }
* \endcode
*
* Some users would have expected that the iterator would be rewinded
* to the "start" of the trailer before calling SerializeTo and DeserializeFrom.
* However, this behavior was not implemented because it cannot be made to
* work reliably for trailers which have a variable size. i.e., if the trailer
* contains options, the code which calls DeserializeFrom cannot rewind
* to the start of the trailer because it does not know the real size of the
* trailer. Hence, to make this legitimate use-case work (variable-sized
* trailers), the input iterator to DeserializeFrom and SerializeTo points
* to the end of the trailer, and not its start.
*/
class Trailer : public Chunk {
public:
virtual ~Trailer ();
private:
/**
* \returns a user-readable name to identify this type of header.
*
* The string returned is expected to be a single word with
* all capital letters
*/
virtual std::string DoGetName (void) const = 0;
/**
* \param os the std output stream in which this
* protocol trailer must print itself.
*
* Although the header is free to format its output as it
* wishes, it is recommended to follow a few rules to integrate
* with the packet pretty printer:
* - start with flags, small field values located between a
* pair of parens. Values should be separated by whitespace.
* - follow the parens with the important fields, separated by
* whitespace.
* i.e.:
* (field1 val1 field2 val2 field3 val3) field4 val4 field5 val5
*/
virtual void PrintTo (std::ostream &os) const = 0;
/**
* \returns the size of the serialized Trailer.
*
* This method is used by Packet::AddTrailer to reserve
* enough room in the packet byte buffer prior to calling
* Trailer::Serialize.
*/
virtual uint32_t GetSerializedSize (void) const = 0;
/**
* \param end the buffer iterator in which the protocol trailer
* must serialize itself. This iterator identifies
* the end of the buffer.
*
* This iterator must be typically moved with the Buffer::Iterator::Prev
* method before writing any byte in the buffer.
*/
virtual void SerializeTo (Buffer::Iterator end) const = 0;
/**
* \param end the buffer iterator from which the protocol trailer must
* deserialize itself. This iterator identifies
* the end of the buffer.
* \returns the number of bytes read from the buffer
*
* This iterator must be typically moved with the Buffer::Iterator::Prev
* method before reading any byte in the buffer. The value returned
* is used to trim the packet byte buffer of the corresponding
* amount when this method is invoked from Packet::RemoveTrailer
*/
virtual uint32_t DeserializeFrom (Buffer::Iterator end) = 0;
};
}; // namespace ns3
#endif /* TRAILER_H */
+245
View File
@@ -0,0 +1,245 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2006 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef UV_TRACE_SOURCE_H
#define UV_TRACE_SOURCE_H
#include "callback-trace-source.h"
#include <stdint.h>
namespace ns3 {
class UVTraceSourceBase {
public:
typedef CallbackTraceSource<uint64_t, uint64_t> ChangeNotifyCallback;
UVTraceSourceBase ()
: m_callback () {}
/* We don't want to copy the base callback. Only setCallback on
* a specific instance will do something to it. */
UVTraceSourceBase (UVTraceSourceBase const &o)
: m_callback () {}
UVTraceSourceBase &operator = (UVTraceSourceBase const &o) {
return *this;
}
~UVTraceSourceBase () {}
void AddCallback (CallbackBase const & callback, TraceContext const & context) {
m_callback.AddCallback (callback, context);
}
void RemoveCallback (CallbackBase const & callback) {
m_callback.RemoveCallback (callback);
}
protected:
void Notify (uint64_t oldVal, uint64_t newVal) {
if (oldVal != newVal)
{
m_callback (oldVal, newVal);
}
}
private:
ChangeNotifyCallback m_callback;
};
template <typename T>
class SVTraceSource;
/**
* \brief trace variables of type "unsigned integer"
* \ingroup lowleveltracing
*
* This template class implements a POD type: it
* behaves like any other variable of type "unsigned integer"
* except that it also reports any changes to its
* value with its internal callback.
*
* To instantiate a 32-bit unsigned variable (to store
* a TCP counter for example), you would create a variable of type
* ns3::UVTraceSource<uint32_t> :
\code
#include <stdint.h>
#include "ns3/uv-trace-source.h"
ns3::UVTraceSource<uint32_t> var;
\endcode
* and you would use it like any other variable of type uint32_t:
\code
var += 12;
var = 10;
\endcode
*/
template <typename T>
class UVTraceSource : public UVTraceSourceBase {
public:
UVTraceSource ()
: m_var ()
{}
UVTraceSource (T const &var)
: m_var (var)
{}
UVTraceSource &operator = (UVTraceSource const &o) {
Assign (o.Get ());
return *this;
}
template <typename TT>
UVTraceSource &operator = (UVTraceSource<TT> const &o) {
Assign (o.Get ());
return *this;
}
template <typename TT>
UVTraceSource &operator = (SVTraceSource<TT> const &o) {
Assign (o.Get ());
return *this;
}
UVTraceSource &operator++ () {
Assign (Get () + 1);
return *this;
}
UVTraceSource &operator-- () {
Assign (Get () - 1);
return *this;
}
UVTraceSource operator++ (int) {
UVTraceSource old (*this);
++*this;
return old;
}
UVTraceSource operator-- (int) {
UVTraceSource old (*this);
--*this;
return old;
}
operator T () const {
return Get ();
}
void Assign (T var) {
Notify (m_var, var);
m_var = var;
}
T Get (void) const {
return m_var;
}
private:
T m_var;
};
template <typename T>
UVTraceSource<T> &operator += (UVTraceSource<T> &lhs, UVTraceSource<T> const &rhs) {
lhs.Assign (lhs.Get () + rhs.Get ());
return lhs;
}
template <typename T>
UVTraceSource<T> &operator -= (UVTraceSource<T> &lhs, UVTraceSource<T> const &rhs) {
lhs.Assign (lhs.Get () - rhs.Get ());
return lhs;
}
template <typename T>
UVTraceSource<T> &operator *= (UVTraceSource<T> &lhs, UVTraceSource<T> const &rhs) {
lhs.Assign (lhs.Get () * rhs.Get ());
return lhs;
}
template <typename T>
UVTraceSource<T> &operator /= (UVTraceSource<T> &lhs, UVTraceSource<T> const &rhs) {
lhs.Assign (lhs.Get () / rhs.Get ());
return lhs;
}
template <typename T>
UVTraceSource<T> &operator <<= (UVTraceSource<T> &lhs, UVTraceSource<T> const &rhs) {
lhs.Assign (lhs.Get () << rhs.Get ());
return lhs;
}
template <typename T>
UVTraceSource<T> &operator >>= (UVTraceSource<T> &lhs, UVTraceSource<T> const &rhs) {
lhs.Assign (lhs.Get () >> rhs.Get ());
return lhs;
}
template <typename T>
UVTraceSource<T> &operator &= (UVTraceSource<T> &lhs, UVTraceSource<T> const &rhs) {
lhs.Assign (lhs.Get () & rhs.Get ());
return lhs;
}
template <typename T>
UVTraceSource<T> &operator |= (UVTraceSource<T> &lhs, UVTraceSource<T> const &rhs) {
lhs.Assign (lhs.Get () | rhs.Get ());
return lhs;
}
template <typename T>
UVTraceSource<T> &operator ^= (UVTraceSource<T> &lhs, UVTraceSource<T> const &rhs) {
lhs.Assign (lhs.Get () ^ rhs.Get ());
return lhs;
}
template <typename T, typename U>
UVTraceSource<T> &operator += (UVTraceSource<T> &lhs, U const &rhs) {
lhs.Assign (lhs.Get () + rhs);
return lhs;
}
template <typename T, typename U>
UVTraceSource<T> &operator -= (UVTraceSource<T> &lhs, U const &rhs) {
lhs.Assign (lhs.Get () - rhs);
return lhs;
}
template <typename T, typename U>
UVTraceSource<T> &operator *= (UVTraceSource<T> &lhs, U const &rhs) {
lhs.Assign (lhs.Get () * rhs);
return lhs;
}
template <typename T, typename U>
UVTraceSource<T> &operator /= (UVTraceSource<T> &lhs, U const &rhs) {
lhs.Assign (lhs.Get () / rhs);
return lhs;
}
template <typename T, typename U>
UVTraceSource<T> &operator <<= (UVTraceSource<T> &lhs, U const &rhs) {
lhs.Assign (lhs.Get () << rhs);
return lhs;
}
template <typename T, typename U>
UVTraceSource<T> &operator >>= (UVTraceSource<T> &lhs, U const &rhs) {
lhs.Assign (lhs.Get () >> rhs);
return lhs;
}
template <typename T, typename U>
UVTraceSource<T> &operator &= (UVTraceSource<T> &lhs, U const &rhs) {
lhs.Assign (lhs.Get () & rhs);
return lhs;
}
template <typename T, typename U>
UVTraceSource<T> &operator |= (UVTraceSource<T> &lhs, U const &rhs) {
lhs.Assign (lhs.Get () | rhs);
return lhs;
}
template <typename T, typename U>
UVTraceSource<T> &operator ^= (UVTraceSource<T> &lhs, U const &rhs) {
lhs.Assign (lhs.Get () ^ rhs);
return lhs;
}
}; // namespace ns3
#endif /* UV_TRACE_SOURCE_H */
+272
View File
@@ -0,0 +1,272 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2006 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "uv-trace-source.h"
#include "sv-trace-source.h"
#include "trace-context.h"
#include "ns3/test.h"
#include "ns3/callback.h"
namespace ns3 {
class Foo {
public:
void Notify (TraceContext const &contex, uint64_t oldVal, uint64_t newVal) {}
};
class VariableTracerTest: public Test {
public:
VariableTracerTest ();
void RunUnsignedTests (void);
void RunSignedUnsignedTests (void);
virtual bool RunTests (void);
};
void
VariableTracerTest::RunUnsignedTests (void)
{
UVTraceSource<uint32_t> var, ovar, tmp;
uint32_t utmp;
Foo *foo = new Foo ();
var.AddCallback (MakeCallback (&Foo::Notify, foo), TraceContext ());
var = 10;
ovar = var;
if (var == ovar)
{
}
if (var != ovar)
{
}
if (var > ovar)
{
}
if (var >= ovar)
{
}
if (var < ovar)
{
}
if (var <= ovar)
if (var == 1)
{
}
if (var != 1)
{
}
if (var > 1)
{
}
if (var >= 1)
{
}
if (var < 1)
{
}
if (var <= 1)
{
}
if (1 == ovar)
{
}
if (1 != ovar)
{
}
if (1 > ovar)
{
}
if (1 >= ovar)
{
}
if (1 < ovar)
{
}
if (1 <= ovar)
{
}
var++;
++var;
var--;
--var;
tmp = var + ovar;
tmp = var - ovar;
tmp = var / ovar;
tmp = var * ovar;
tmp = var << ovar;
tmp = var >> ovar;
tmp = var & ovar;
tmp = var | ovar;
tmp = var ^ ovar;
tmp = var + 1;
tmp = var - 1;
tmp = var / 1;
tmp = var * 1;
tmp = var << 1;
tmp = var >> 1;
tmp = var & 1;
tmp = var | 1;
tmp = var ^ 1;
tmp = 1 + ovar;
tmp = 1 - ovar;
tmp = 1 / ovar;
tmp = 1 * ovar;
tmp = 1 << ovar;
tmp = 1 >> ovar;
tmp = 1 & ovar;
tmp = 1 | ovar;
tmp = 1 ^ ovar;
tmp += var;
tmp -= var;
tmp /= var;
tmp *= var;
tmp <<= var;
tmp >>= var;
tmp &= var;
tmp |= var;
tmp ^= var;
tmp += 1;
tmp -= 1;
tmp /= 1;
tmp *= 1;
tmp <<= 1;
tmp >>= 1;
tmp &= 1;
tmp |= 1;
tmp ^= 1;
utmp = var + ovar;
utmp = var - ovar;
utmp = var / ovar;
utmp = var * ovar;
utmp = var << ovar;
utmp = var >> ovar;
utmp = var & ovar;
utmp = var | ovar;
utmp = var ^ ovar;
utmp = var + 1;
utmp = var - 1;
utmp = var / 1;
utmp = var * 1;
utmp = var << 1;
utmp = var >> 1;
utmp = var & 1;
utmp = var | 1;
utmp = var ^ 1;
utmp = 1 + ovar;
utmp = 1 - ovar;
utmp = 1 / ovar;
utmp = 1 * ovar;
utmp = 1 << ovar;
utmp = 1 >> ovar;
utmp = 1 & ovar;
utmp = 1 | ovar;
utmp = 1 ^ ovar;
utmp += var;
utmp -= var;
utmp /= var;
utmp *= var;
utmp <<= var;
utmp >>= var;
utmp &= var;
utmp |= var;
utmp ^= var;
utmp += 1;
utmp -= 1;
utmp /= 1;
utmp *= 1;
utmp <<= 1;
utmp >>= 1;
utmp &= 1;
utmp |= 1;
utmp ^= 1;
delete foo;
}
void
VariableTracerTest::RunSignedUnsignedTests (void)
{
unsigned short utmp = 10;
unsigned int uitmp = 7;
short stmp = 5;
utmp = stmp;
utmp += stmp;
uitmp = utmp;
utmp = uitmp;
UVTraceSource<unsigned short> uvar = 10;
UVTraceSource<unsigned int> uivar = 5;
SVTraceSource<short> svar = 5;
SVTraceSource<int> sivar = 5;
uvar = svar;
svar = uvar;
uvar += svar;
svar += uvar;
uvar = sivar;
sivar = uvar;
uvar += sivar;
sivar += uvar;
uivar = uvar;
uvar = uivar;
uivar += uvar;
uvar += uivar;
sivar = svar;
svar = sivar;
sivar += svar;
svar += sivar;
}
bool
VariableTracerTest::RunTests (void)
{
RunUnsignedTests ();
RunSignedUnsignedTests ();
return true;
}
VariableTracerTest::VariableTracerTest ()
: Test ("VariableTracer") {}
static VariableTracerTest gVariableTracerTest;
}; // namespace ns3
+50
View File
@@ -0,0 +1,50 @@
## -*- 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.uselib_local = ['ns3-core', 'ns3-simulator']
common.source = [
'buffer.cc',
'chunk.cc',
'header.cc',
'trailer.cc',
'packet-printer.cc',
'packet-metadata.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',
'chunk.h',
'header.h',
'trailer.h',
'tags.h',
'packet.h',
'packet-printer.h',
'packet-metadata.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',
'data-rate.h',
]
+41
View File
@@ -0,0 +1,41 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2006 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "assert.h"
namespace ns3 {
void
AssertBreakpoint (void)
{
int *a = 0;
/**
* we test here to allow a debugger to change the value of
* the variable 'a' to allow the debugger to avoid the
* subsequent segfault.
*/
if (a == 0)
{
*a = 0;
}
}
}//namespace ns3
+104
View File
@@ -0,0 +1,104 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2006 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef ASSERT_H
#define ASSERT_H
/**
* \defgroup assert Assert
* \brief assert functions and macros
*
* The assert macros are used to verify
* at runtime that a certain condition is true. If it is
* not true, the program halts. These checks are built
* into the program only in debugging builds. They are
* removed in optimized builds.
*/
namespace ns3 {
/**
* \ingroup debugging
*
* When an NS_ASSERT cannot verify its condition,
* this function is called. This is where you should
* be able to put a breakpoint with a debugger if
* you want to catch assertions before the program
* halts.
*/
void AssertBreakpoint (void);
}//namespace ns3
#ifdef NS3_ASSERT_ENABLE
#include <iostream>
/**
* \ingroup assert
* \param condition condition to verifiy.
*
* At runtime, in debugging builds, if this condition is not
* true, the program prints the source file, line number and
* unverified condition and halts in the ns3::AssertBreakpoint
* function.
*/
#define NS_ASSERT(condition) \
do \
{ \
if (!(condition)) \
{ \
std::cout << "assert failed. file=" << __FILE__ << \
", line=" << __LINE__ << ", cond=\""#condition << \
"\"" << std::endl; \
ns3::AssertBreakpoint (); \
} \
} \
while (false)
/**
* \ingroup assert
* \param condition condition to verifiy.
* \param message message to output
*
* At runtime, in debugging builds, if this condition is not
* true, the program prints the message to output and
* halts in the ns3::AssertBreakpoint function.
*/
#define NS_ASSERT_MSG(condition, message) \
do \
{ \
if (!(condition)) \
{ \
std::cout << message << std::endl; \
ns3::AssertBreakpoint (); \
} \
} \
while (false)
#else /* NS3_ASSERT_ENABLE */
#define NS_ASSERT(cond)
#define NS_ASSERT_MSG(cond,msg)
#endif /* NS3_ASSERT_ENABLE */
#endif /* ASSERT_H */
+226
View File
@@ -0,0 +1,226 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2005,2006 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "test.h"
#include "callback.h"
#include <stdint.h>
#ifdef RUN_SELF_TESTS
namespace ns3 {
static bool gTest5 = false;
static bool gTest6 = false;
static bool gTest7 = false;
void Test5 (void)
{
gTest5 = true;
}
void Test6 (int)
{
gTest6 = true;
}
int Test7 (int a)
{
gTest7 = true;
return a;
}
void *Test9 (bool *a)
{
return a;
}
void *Test10 (bool *a, int const & b)
{
return a;
}
class CallbackTest : public ns3::Test {
private:
bool m_test1;
bool m_test2;
bool m_test3;
bool m_test4;
public:
CallbackTest ();
virtual bool RunTests (void);
void Reset (void);
bool IsWrong (void);
void Test1 (void);
int Test2 (void);
void Test3 (double a);
int Test4 (double a, int b);
void Test8 (Callback<void, int> callback);
};
CallbackTest::CallbackTest ()
: ns3::Test ("Callback"),
m_test1 (false),
m_test2 (false),
m_test3 (false),
m_test4 (false)
{}
void
CallbackTest::Test1 (void)
{
m_test1 = true;
}
int
CallbackTest::Test2 (void)
{
m_test2 = true;
return 2;
}
void
CallbackTest::Test3 (double a)
{
m_test3 = true;
}
int
CallbackTest::Test4 (double a, int b)
{
m_test4 = true;
return 4;
}
void
CallbackTest::Test8 (Callback<void,int> callback)
{
callback (3);
}
bool
CallbackTest::IsWrong (void)
{
if (!m_test1 ||
!m_test2 ||
!m_test3 ||
!m_test4 ||
!gTest5 ||
!gTest6 ||
!gTest7)
{
return true;
}
return false;
}
void
CallbackTest::Reset (void)
{
m_test1 = false;
m_test2 = false;
m_test3 = false;
m_test4 = false;
gTest5 = false;
gTest6 = false;
gTest7 = false;
}
bool
CallbackTest::RunTests (void)
{
bool ok = true;
typedef ns3::Callback<void> A;
typedef ns3::Callback<int> B;
typedef ns3::Callback<void, double> C;
typedef ns3::Callback<int, double, int> D;
typedef ns3::Callback<void> E;
typedef ns3::Callback<void,int> F;
typedef ns3::Callback<int,int> G;
A a0 (this, &CallbackTest::Test1);
B b0;
b0 = B (this, &CallbackTest::Test2);
C c0 = C (this, &CallbackTest::Test3);
D d0 = D (this, &CallbackTest::Test4);
E e0 = E (&Test5, true, true);
F f0 = F (&Test6, true, true);
G g0 = G (&Test7, true, true);
a0 ();
b0 ();
c0 (0.0);
d0 (0.0, 1);
e0 ();
f0 (1);
g0 (1);
if (IsWrong ())
{
ok = false;
}
Reset ();
A a1 = ns3::MakeCallback (&CallbackTest::Test1, this);
B b1 = ns3::MakeCallback (&CallbackTest::Test2, this);
C c1 = ns3::MakeCallback (&CallbackTest::Test3, this);
D d1 = ns3::MakeCallback (&CallbackTest::Test4, this);
E e1 = ns3::MakeCallback (&Test5);
F f1 = ns3::MakeCallback (&Test6);
G g1 = ns3::MakeCallback (&Test7);
a1 ();
b1 ();
c1 (0.0);
d1 (0.0, 1);
e1 ();
f1 (1);
g1 (2);
a1.Nullify ();
b1.Nullify ();
c1.Nullify ();
d1.Nullify ();
e1.Nullify ();
g1.Nullify ();
Test8 (f1);
f1.Nullify ();
Callback<void, int64_t,int64_t> a2;
if (IsWrong ())
{
ok = false;
}
MakeBoundCallback (&Test7, 0);
bool v;
MakeBoundCallback (&Test9, &v);
MakeBoundCallback (&Test10, &v);
return ok;
}
static CallbackTest gCallbackTest;
}; // namespace
#endif /* RUN_SELF_TESTS */
+678
View File
@@ -0,0 +1,678 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2005,2006 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef CALLBACK_H
#define CALLBACK_H
#include "ptr.h"
#include "fatal-error.h"
#include "empty.h"
namespace ns3 {
/***
* \internal
* This code was originally written based on the techniques
* described in http://www.codeproject.com/cpp/TTLFunction.asp
* It was subsequently rewritten to follow the architecture
* outlined in "Modern C++ Design" by Andrei Alexandrescu in
* chapter 5, "Generalized Functors".
*
* This code uses:
* - default template parameters to saves users from having to
* specify empty parameters when the number of parameters
* is smaller than the maximum supported number
* - the pimpl idiom: the Callback class is passed around by
* value and delegates the crux of the work to its pimpl
* pointer.
* - two pimpl implementations which derive from CallbackImpl
* FunctorCallbackImpl can be used with any functor-type
* while MemPtrCallbackImpl can be used with pointers to
* member functions.
* - a reference list implementation to implement the Callback's
* value semantics.
*
* This code most notably departs from the alexandrescu
* implementation in that it does not use type lists to specify
* and pass around the types of the callback arguments.
* Of course, it also does not use copy-destruction semantics
* and relies on a reference list rather than autoPtr to hold
* the pointer.
*/
template <typename T>
struct CallbackTraits;
template <typename T>
struct CallbackTraits<T *>
{
static T & GetReference (T * const p)
{
return *p;
}
};
class CallbackImplBase {
public:
CallbackImplBase ()
: m_count (1) {}
virtual ~CallbackImplBase () {}
void Ref (void) {
m_count++;
}
void Unref (void) {
m_count--;
if (m_count == 0) {
delete this;
}
}
virtual bool IsEqual (CallbackImplBase const *other) const = 0;
private:
uint32_t m_count;
};
// declare the CallbackImpl class
template <typename R, typename T1, typename T2, typename T3, typename T4, typename T5>
class CallbackImpl;
// define CallbackImpl for 0 params
template <typename R>
class CallbackImpl<R,empty,empty,empty,empty,empty> : public CallbackImplBase {
public:
virtual ~CallbackImpl () {}
virtual R operator() (void) = 0;
};
// define CallbackImpl for 1 params
template <typename R, typename T1>
class CallbackImpl<R,T1,empty,empty,empty,empty> : public CallbackImplBase {
public:
virtual ~CallbackImpl () {}
virtual R operator() (T1) = 0;
};
// define CallbackImpl for 2 params
template <typename R, typename T1, typename T2>
class CallbackImpl<R,T1,T2,empty,empty,empty> : public CallbackImplBase {
public:
virtual ~CallbackImpl () {}
virtual R operator() (T1, T2) = 0;
};
// define CallbackImpl for 3 params
template <typename R, typename T1, typename T2, typename T3>
class CallbackImpl<R,T1,T2,T3,empty,empty> : public CallbackImplBase {
public:
virtual ~CallbackImpl () {}
virtual R operator() (T1, T2, T3) = 0;
};
// define CallbackImpl for 4 params
template <typename R, typename T1, typename T2, typename T3, typename T4>
class CallbackImpl<R,T1,T2,T3,T4,empty> : public CallbackImplBase {
public:
virtual ~CallbackImpl () {}
virtual R operator() (T1, T2, T3, T4) = 0;
};
// define CallbackImpl for 5 params
template <typename R, typename T1, typename T2, typename T3, typename T4, typename T5>
class CallbackImpl : public CallbackImplBase {
public:
virtual ~CallbackImpl () {}
virtual R operator() (T1, T2, T3, T4, T5) = 0;
};
// an impl for Functors:
template <typename T, typename R, typename T1, typename T2, typename T3, typename T4,typename T5>
class FunctorCallbackImpl : public CallbackImpl<R,T1,T2,T3,T4,T5> {
public:
FunctorCallbackImpl (T const &functor)
: m_functor (functor) {}
virtual ~FunctorCallbackImpl () {}
R operator() (void) {
return m_functor ();
}
R operator() (T1 a1) {
return m_functor (a1);
}
R operator() (T1 a1,T2 a2) {
return m_functor (a1,a2);
}
R operator() (T1 a1,T2 a2,T3 a3) {
return m_functor (a1,a2,a3);
}
R operator() (T1 a1,T2 a2,T3 a3,T4 a4) {
return m_functor (a1,a2,a3,a4);
}
R operator() (T1 a1,T2 a2,T3 a3,T4 a4,T5 a5) {
return m_functor (a1,a2,a3,a4,a5);
}
virtual bool IsEqual (CallbackImplBase const *other) const {
FunctorCallbackImpl<T,R,T1,T2,T3,T4,T5> const *otherDerived =
dynamic_cast<FunctorCallbackImpl<T,R,T1,T2,T3,T4,T5> const *> (other);
if (otherDerived == 0)
{
return false;
}
else if (otherDerived->m_functor != m_functor)
{
return false;
}
return true;
}
private:
T m_functor;
};
// an impl for pointer to member functions
template <typename OBJ_PTR, typename MEM_PTR, typename R, typename T1, typename T2, typename T3, typename T4, typename T5>
class MemPtrCallbackImpl : public CallbackImpl<R,T1,T2,T3,T4,T5> {
public:
MemPtrCallbackImpl (OBJ_PTR const&objPtr, MEM_PTR mem_ptr)
: m_objPtr (objPtr), m_memPtr (mem_ptr) {}
virtual ~MemPtrCallbackImpl () {}
R operator() (void) {
return ((CallbackTraits<OBJ_PTR>::GetReference (m_objPtr)).*m_memPtr) ();
}
R operator() (T1 a1) {
return ((CallbackTraits<OBJ_PTR>::GetReference (m_objPtr)).*m_memPtr) (a1);
}
R operator() (T1 a1,T2 a2) {
return ((CallbackTraits<OBJ_PTR>::GetReference (m_objPtr)).*m_memPtr) (a1, a2);
}
R operator() (T1 a1,T2 a2,T3 a3) {
return ((CallbackTraits<OBJ_PTR>::GetReference (m_objPtr)).*m_memPtr) (a1, a2, a3);
}
R operator() (T1 a1,T2 a2,T3 a3,T4 a4) {
return ((CallbackTraits<OBJ_PTR>::GetReference (m_objPtr)).*m_memPtr) (a1, a2, a3, a4);
}
R operator() (T1 a1,T2 a2,T3 a3,T4 a4,T5 a5) {
return ((CallbackTraits<OBJ_PTR>::GetReference (m_objPtr)).*m_memPtr) (a1, a2, a3, a4, a5);
}
virtual bool IsEqual (CallbackImplBase const *other) const {
MemPtrCallbackImpl<OBJ_PTR,MEM_PTR,R,T1,T2,T3,T4,T5> const *otherDerived =
dynamic_cast<MemPtrCallbackImpl<OBJ_PTR,MEM_PTR,R,T1,T2,T3,T4,T5> const *> (other);
if (otherDerived == 0)
{
return false;
}
else if (otherDerived->m_objPtr != m_objPtr ||
otherDerived->m_memPtr != m_memPtr)
{
return false;
}
return true;
}
private:
OBJ_PTR const m_objPtr;
MEM_PTR m_memPtr;
};
class CallbackBase {
public:
virtual ~CallbackBase () {}
virtual CallbackImplBase *PeekImpl (void) const = 0;
virtual Ptr<CallbackImplBase> GetImpl (void) const = 0;
};
/**
* \brief Callback template class
*
* This class template implements the Functor Design Pattern.
* It is used to declare the type of a Callback:
* - the first non-optional template argument represents
* the return type of the callback.
* - the second optional template argument represents
* the type of the first argument to the callback.
* - the third optional template argument represents
* the type of the second argument to the callback.
* - the fourth optional template argument represents
* the type of the third argument to the callback.
* - the fifth optional template argument represents
* the type of the fourth argument to the callback.
* - the sixth optional template argument represents
* the type of the fifth argument to the callback.
*
* Callback instances are built with the \ref MakeCallback
* template functions. Callback instances have POD semantics:
* the memory they allocate is managed automatically, without
* user intervention which allows you to pass around Callback
* instances by value.
*
* Sample code which shows how to use this class template
* as well as the function templates \ref MakeCallback :
* \include samples/main-callback.cc
*/
template<typename R,
typename T1 = empty, typename T2 = empty,
typename T3 = empty, typename T4 = empty,
typename T5 = empty>
class Callback : public CallbackBase {
public:
// There are two dummy args below to ensure that this constructor is
// always properly disambiguited by the c++ compiler
template <typename FUNCTOR>
Callback (FUNCTOR const &functor, bool, bool)
: m_impl (Create<FunctorCallbackImpl<FUNCTOR,R,T1,T2,T3,T4,T5> > (functor))
{}
template <typename OBJ_PTR, typename MEM_PTR>
Callback (OBJ_PTR const &objPtr, MEM_PTR mem_ptr)
: m_impl (Create<MemPtrCallbackImpl<OBJ_PTR,MEM_PTR,R,T1,T2,T3,T4,T5> > (objPtr, mem_ptr))
{}
Callback (Ptr<CallbackImpl<R,T1,T2,T3,T4,T5> > const &impl)
: m_impl (impl)
{}
bool IsNull (void) const {
return (PeekImpl () == 0)?true:false;
}
void Nullify (void) {
m_impl = 0;
}
Callback () : m_impl () {}
R operator() (void) const {
return (*(PeekImpl ())) ();
}
R operator() (T1 a1) const {
return (*(PeekImpl ())) (a1);
}
R operator() (T1 a1, T2 a2) const {
return (*(PeekImpl ())) (a1,a2);
}
R operator() (T1 a1, T2 a2, T3 a3) const {
return (*(PeekImpl ())) (a1,a2,a3);
}
R operator() (T1 a1, T2 a2, T3 a3, T4 a4) const {
return (*(PeekImpl ())) (a1,a2,a3,a4);
}
R operator() (T1 a1, T2 a2, T3 a3, T4 a4,T5 a5) const {
return (*(PeekImpl ())) (a1,a2,a3,a4,a5);
}
bool IsEqual (CallbackBase const &other) {
return PeekImpl ()->IsEqual (other.PeekImpl ());
}
bool CheckType (CallbackBase const& other) {
CallbackImplBase *otherBase = other.PeekImpl ();
if (dynamic_cast<CallbackImpl<R,T1,T2,T3,T4,T5> *> (otherBase) != 0)
{
return true;
}
else
{
return false;
}
}
void Assign (CallbackBase const &other) {
if (!CheckType (other))
{
NS_FATAL_ERROR ("Incompatible types. (feed to \"c++filt -t\")"
" got=" << typeid (other).name () <<
", expected=" << typeid (*this).name ());
}
const Callback<R, T1,T2,T3,T4,T5> *goodType = static_cast<const Callback<R,T1,T2,T3,T4,T5> *> (&other);
*this = *goodType;
}
void Assign (Ptr<CallbackImplBase> other) {
CallbackImpl<R,T1,T2,T3,T4,T5> *impl = dynamic_cast<CallbackImpl<R,T1,T2,T3,T4,T5> *> (PeekPointer (other));
if (other == 0)
{
NS_FATAL_ERROR ("Incompatible types. (feed to \"c++filt -t\")"
" got=" << typeid (other).name () <<
", expected=" << typeid (*impl).name ());
}
*this = Callback<R,T1,T2,T3,T4,T5> (impl);
}
virtual Ptr<CallbackImplBase>GetImpl (void) const {
return m_impl;
}
private:
virtual CallbackImpl<R,T1,T2,T3,T4,T5> *PeekImpl (void) const {
return PeekPointer (m_impl);
}
Ptr<CallbackImpl<R,T1,T2,T3,T4,T5> > m_impl;
};
/**
* \defgroup MakeCallback MakeCallback
*
*/
/**
* \ingroup MakeCallback
* \param mem_ptr class method member pointer
* \param objPtr class instance
* \return a wrapper Callback
* Build Callbacks for class method members which takes no arguments
* and potentially return a value.
*/
template <typename T, typename OBJ, typename R>
Callback<R> MakeCallback (R (T::*memPtr) (void), OBJ objPtr) {
return Callback<R> (objPtr, memPtr);
}
template <typename T, typename OBJ, typename R>
Callback<R> MakeCallback (R (T::*mem_ptr) () const, OBJ const objPtr) {
return Callback<R> (objPtr, mem_ptr);
}
/**
* \ingroup MakeCallback
* \param mem_ptr class method member pointer
* \param objPtr class instance
* \return a wrapper Callback
* Build Callbacks for class method members which takes one argument
* and potentially return a value.
*/
template <typename T, typename OBJ, typename R, typename T1>
Callback<R,T1> MakeCallback (R (T::*mem_ptr) (T1), OBJ *const objPtr) {
return Callback<R,T1> (objPtr, mem_ptr);
}
template <typename T, typename OBJ, typename R, typename T1>
Callback<R,T1> MakeCallback (R (T::*mem_ptr) (T1) const, OBJ const *const objPtr) {
return Callback<R,T1> (objPtr, mem_ptr);
}
/**
* \ingroup MakeCallback
* \param mem_ptr class method member pointer
* \param objPtr class instance
* \return a wrapper Callback
* Build Callbacks for class method members which takes two arguments
* and potentially return a value.
*/
template <typename T, typename OBJ, typename R, typename T1, typename T2>
Callback<R,T1,T2> MakeCallback (R (T::*mem_ptr) (T1,T2), OBJ *const objPtr) {
return Callback<R,T1,T2> (objPtr, mem_ptr);
}
template <typename T, typename OBJ, typename R, typename T1, typename T2>
Callback<R,T1,T2> MakeCallback (R (T::*mem_ptr) (T1,T2) const, OBJ const*const objPtr) {
return Callback<R,T1,T2> (objPtr, mem_ptr);
}
/**
* \ingroup MakeCallback
* \param mem_ptr class method member pointer
* \param objPtr class instance
* \return a wrapper Callback
* Build Callbacks for class method members which takes three arguments
* and potentially return a value.
*/
template <typename T, typename OBJ, typename R, typename T1,typename T2, typename T3>
Callback<R,T1,T2,T3> MakeCallback (R (T::*mem_ptr) (T1,T2,T3), OBJ *const objPtr) {
return Callback<R,T1,T2,T3> (objPtr, mem_ptr);
}
template <typename T, typename OBJ, typename R, typename T1,typename T2, typename T3>
Callback<R,T1,T2,T3> MakeCallback (R (T::*mem_ptr) (T1,T2,T3) const, OBJ const*const objPtr) {
return Callback<R,T1,T2,T3> (objPtr, mem_ptr);
}
/**
* \ingroup MakeCallback
* \param mem_ptr class method member pointer
* \param objPtr class instance
* \return a wrapper Callback
* Build Callbacks for class method members which takes four arguments
* and potentially return a value.
*/
template <typename T, typename OBJ, typename R, typename T1, typename T2, typename T3, typename T4>
Callback<R,T1,T2,T3,T4> MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4), OBJ *const objPtr) {
return Callback<R,T1,T2,T3,T4> (objPtr, mem_ptr);
}
template <typename T, typename OBJ, typename R, typename T1, typename T2, typename T3, typename T4>
Callback<R,T1,T2,T3,T4> MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4) const, OBJ const*const objPtr) {
return Callback<R,T1,T2,T3,T4> (objPtr, mem_ptr);
}
/**
* \ingroup MakeCallback
* \param mem_ptr class method member pointer
* \param objPtr class instance
* \return a wrapper Callback
* Build Callbacks for class method members which takes five arguments
* and potentially return a value.
*/
template <typename T, typename OBJ, typename R, typename T1, typename T2, typename T3, typename T4,typename T5>
Callback<R,T1,T2,T3,T4,T5> MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4,T5), OBJ *const objPtr) {
return Callback<R,T1,T2,T3,T4,T5> (objPtr, mem_ptr);
}
template <typename T, typename OBJ, typename R, typename T1, typename T2, typename T3, typename T4,typename T5>
Callback<R,T1,T2,T3,T4,T5> MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4,T5) const, OBJ const*const objPtr) {
return Callback<R,T1,T2,T3,T4,T5> (objPtr, mem_ptr);
}
/**
* \ingroup MakeCallback
* \param fnPtr function pointer
* \return a wrapper Callback
* Build Callbacks for functions which takes no arguments
* and potentially return a value.
*/
template <typename R>
Callback<R> MakeCallback (R (*fnPtr) ()) {
return Callback<R> (fnPtr, true, true);
}
/**
* \ingroup MakeCallback
* \param fnPtr function pointer
* \return a wrapper Callback
* Build Callbacks for functions which takes one argument
* and potentially return a value.
*/
template <typename R, typename T1>
Callback<R,T1> MakeCallback (R (*fnPtr) (T1)) {
return Callback<R,T1> (fnPtr, true, true);
}
/**
* \ingroup MakeCallback
* \param fnPtr function pointer
* \return a wrapper Callback
* Build Callbacks for functions which takes two arguments
* and potentially return a value.
*/
template <typename R, typename T1, typename T2>
Callback<R,T1,T2> MakeCallback (R (*fnPtr) (T1,T2)) {
return Callback<R,T1,T2> (fnPtr, true, true);
}
/**
* \ingroup MakeCallback
* \param fnPtr function pointer
* \return a wrapper Callback
* Build Callbacks for functions which takes three arguments
* and potentially return a value.
*/
template <typename R, typename T1, typename T2,typename T3>
Callback<R,T1,T2,T3> MakeCallback (R (*fnPtr) (T1,T2,T3)) {
return Callback<R,T1,T2,T3> (fnPtr, true, true);
}
/**
* \ingroup MakeCallback
* \param fnPtr function pointer
* \return a wrapper Callback
* Build Callbacks for functions which takes four arguments
* and potentially return a value.
*/
template <typename R, typename T1, typename T2,typename T3,typename T4>
Callback<R,T1,T2,T3,T4> MakeCallback (R (*fnPtr) (T1,T2,T3,T4)) {
return Callback<R,T1,T2,T3,T4> (fnPtr, true, true);
}
/**
* \ingroup MakeCallback
* \param fnPtr function pointer
* \return a wrapper Callback
* Build Callbacks for functions which takes five arguments
* and potentially return a value.
*/
template <typename R, typename T1, typename T2,typename T3,typename T4,typename T5>
Callback<R,T1,T2,T3,T4,T5> MakeCallback (R (*fnPtr) (T1,T2,T3,T4,T5)) {
return Callback<R,T1,T2,T3,T4,T5> (fnPtr, true, true);
}
/**
* \ingroup MakeCallback
* \return a wrapper Callback
* Build a null callback which takes no arguments
* and potentially return a value.
*/
template <typename R>
Callback<R> MakeNullCallback (void) {
return Callback<R> ();
}
/**
* \ingroup MakeCallback
* \overload Callback<R> MakeNullCallback (void)
* \return a wrapper Callback
* Build a null callback which takes one argument
* and potentially return a value.
*/
template <typename R, typename T1>
Callback<R,T1> MakeNullCallback (void) {
return Callback<R,T1> ();
}
/**
* \ingroup MakeCallback
* \overload Callback<R> MakeNullCallback (void)
* \return a wrapper Callback
* Build a null callback which takes two arguments
* and potentially return a value.
*/
template <typename R, typename T1, typename T2>
Callback<R,T1,T2> MakeNullCallback (void) {
return Callback<R,T1,T2> ();
}
/**
* \ingroup MakeCallback
* \overload Callback<R> MakeNullCallback (void)
* \return a wrapper Callback
* Build a null callback which takes three arguments
* and potentially return a value.
*/
template <typename R, typename T1, typename T2,typename T3>
Callback<R,T1,T2,T3> MakeNullCallback (void) {
return Callback<R,T1,T2,T3> ();
}
/**
* \ingroup MakeCallback
* \overload Callback<R> MakeNullCallback (void)
* \return a wrapper Callback
* Build a null callback which takes four arguments
* and potentially return a value.
*/
template <typename R, typename T1, typename T2,typename T3,typename T4>
Callback<R,T1,T2,T3,T4> MakeNullCallback (void) {
return Callback<R,T1,T2,T3,T4> ();
}
/**
* \ingroup MakeCallback
* \overload Callback<R> MakeNullCallback (void)
* \return a wrapper Callback
* Build a null callback which takes five arguments
* and potentially return a value.
*/
template <typename R, typename T1, typename T2,typename T3,typename T4,typename T5>
Callback<R,T1,T2,T3,T4,T5> MakeNullCallback (void) {
return Callback<R,T1,T2,T3,T4,T5> ();
}
/*
* The following is experimental code. It works but we have
* not yet determined whether or not it is really useful and whether
* or not we really want to use it.
*/
// an impl for Bound Functors:
template <typename T, typename R, typename TX, typename T1, typename T2, typename T3, typename T4,typename T5>
class BoundFunctorCallbackImpl : public CallbackImpl<R,T1,T2,T3,T4,T5> {
public:
BoundFunctorCallbackImpl (T const &functor, TX a)
: m_functor (functor), m_a (a) {}
virtual ~BoundFunctorCallbackImpl () {}
R operator() (void) {
return m_functor (m_a);
}
R operator() (T1 a1) {
return m_functor (m_a,a1);
}
R operator() (T1 a1,T2 a2) {
return m_functor (m_a,a1,a2);
}
R operator() (T1 a1,T2 a2,T3 a3) {
return m_functor (m_a,a1,a2,a3);
}
R operator() (T1 a1,T2 a2,T3 a3,T4 a4) {
return m_functor (m_a,a1,a2,a3,a4);
}
R operator() (T1 a1,T2 a2,T3 a3,T4 a4,T5 a5) {
return m_functor (m_a,a1,a2,a3,a4,a5);
}
virtual bool IsEqual (CallbackImplBase const *other) const {
BoundFunctorCallbackImpl<T,R,TX,T1,T2,T3,T4,T5> const *otherDerived =
dynamic_cast<BoundFunctorCallbackImpl<T,R,TX,T1,T2,T3,T4,T5> const *> (other);
if (otherDerived == 0)
{
return false;
}
else if (otherDerived->m_functor != m_functor ||
otherDerived->m_a != m_a)
{
return false;
}
return true;
}
private:
T m_functor;
TX m_a;
};
template <typename R, typename TX>
Callback<R> MakeBoundCallback (R (*fnPtr) (TX), TX a) {
Ptr<CallbackImpl<R,empty,empty,empty,empty,empty> > impl =
Create<BoundFunctorCallbackImpl<R (*) (TX),R,TX,empty,empty,empty,empty,empty> >(fnPtr, a);
return Callback<R> (impl);
}
template <typename R, typename TX, typename T1>
Callback<R,T1> MakeBoundCallback (R (*fnPtr) (TX,T1), TX a) {
Ptr<CallbackImpl<R,T1,empty,empty,empty,empty> > impl =
Create<BoundFunctorCallbackImpl<R (*) (TX,T1),R,TX,T1,empty,empty,empty,empty> > (fnPtr, a);
return Callback<R,T1> (impl);
}
template <typename R, typename TX, typename T1, typename T2>
Callback<R,T1,T2> MakeBoundCallback (R (*fnPtr) (TX,T1,T2), TX a) {
Ptr<CallbackImpl<R,T1,T2,empty,empty,empty> > impl =
Create<BoundFunctorCallbackImpl<R (*) (TX,T1,T2),R,TX,T1,T2,empty,empty,empty> > (fnPtr, a);
return Callback<R,T1,T2> (impl);
}
template <typename R, typename TX, typename T1, typename T2,typename T3,typename T4>
Callback<R,T1,T2,T3,T4> MakeBoundCallback (R (*fnPtr) (TX,T1,T2,T3,T4), TX a) {
Ptr<CallbackImpl<R,T1,T2,T3,T4,empty> > impl =
Create<BoundFunctorCallbackImpl<R (*) (TX,T1,T2,T3,T4),R,TX,T1,T2,T3,T4,empty> > (fnPtr, a);
return Callback<R,T1,T2,T3,T4> (impl);
}
template <typename R, typename TX, typename T1, typename T2,typename T3,typename T4,typename T5>
Callback<R,T1,T2,T3,T4,T5> MakeBoundCallback (R (*fnPtr) (TX,T1,T2,T3,T4,T5), TX a) {
Ptr<CallbackImpl<R,T1,T2,T3,T4,T5> > impl =
Create<BoundFunctorCallbackImpl<R (*) (TX,T1,T2,T3,T4,T5),R,TX,T1,T2,T3,T4,T5> > (fnPtr, a);
return Callback<R,T1,T2,T3,T4,T5> (impl);
}
}; // namespace ns3
#endif /* CALLBACK_H */
+150
View File
@@ -0,0 +1,150 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 Georgia Tech University, INRIA
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Authors: Raj Bhattacharjea <raj.b@gatech.edu>,
* Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "command-line.h"
#include <unistd.h>
namespace ns3 {
CommandDefaultValue CommandLine::g_help ("help",
"Print Help text for all commands",
MakeCallback (&CommandLine::PrintHelp));
void
CommandLine::AddArgCommand (const std::string &name,
const std::string &help,
Callback<void> cb)
{
DefaultValueBase *base =
new CommandDefaultValue (name, help, cb);
GetUserList ()->push_back (base);
}
CommandLine::List *
CommandLine::GetUserList (void)
{
static List list;
return &list;
}
void
CommandLine::PrintHelp (void)
{
for (List::iterator i = GetUserList ()->begin ();
i != GetUserList ()->end (); i++)
{
DefaultValueBase *item = *i;
if (item->GetType () == "" &&
item->GetDefaultValue () == "")
{
std::cout << "--" << item->GetName () << "\t" << item->GetHelp () << std::endl;
}
else
{
std::cout << "--" << item->GetName () << "=[" << item->GetType () << ":"
<< item->GetDefaultValue () << "]\t" << item->GetHelp () << std::endl;
}
}
for (List::iterator i = DefaultValueList::Begin ();
i != DefaultValueList::End (); i++)
{
DefaultValueBase *item = *i;
if (item->GetType () == "" &&
item->GetDefaultValue () == "")
{
std::cout << "--" << item->GetName () << "\t" << item->GetHelp () << std::endl;
}
else
{
std::cout << "--" << item->GetName () << "=[" << item->GetType () << ":"
<< item->GetDefaultValue () << "]\t" << item->GetHelp () << std::endl;
}
}
// XXX on win32, do the right thing here.
exit (0);
}
void
CommandLine::Parse (int argc, char *argv[])
{
argc--;
argv++;
while (argc > 0)
{
// remove "--" or "-" heading.
std::string param = *argv;
std::string::size_type cur = param.find ("--");
if (cur == std::string::npos)
{
cur = param.find ("-");
if (cur == std::string::npos)
{
// invalid argument. ignore it.
continue;
}
}
if (cur != 0)
{
// invalid argument. ignore it.
continue;
}
param = std::string (param, 2, param.size ());
cur = param.find ("=");
std::string name, value;
if (cur == std::string::npos)
{
name = param;
value = "";
}
else
{
name = std::string (param, 0, cur);
value = std::string (param, cur + 1, std::string::npos);
}
// try to find this argument in the user args.
for (List::iterator i = GetUserList ()->begin ();
i != GetUserList ()->end (); i++)
{
DefaultValueBase *item = *i;
if (item->GetName () == name)
{
item->ParseValue (value);
continue;
}
}
// try to find this argument in the default args.
for (List::iterator i = DefaultValueList::Begin ();
i != DefaultValueList::End (); i++)
{
DefaultValueBase *item = *i;
if (item->GetName () == name)
{
item->ParseValue (value);
continue;
}
}
argc--;
argv++;
}
}
}//namespace ns3
+144
View File
@@ -0,0 +1,144 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 Georgia Tech University, INRIA
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Authors: Raj Bhattacharjea <raj.b@gatech.edu>,
* Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef COMMAND_LINE_H
#define COMMAND_LINE_H
#include <list>
#include <string>
#include "default-value.h"
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 <typename T>
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 cb 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<void> 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 <typename T>
class UserDefaultValue : public DefaultValueBase
{
public:
UserDefaultValue (const std::string &name,
const std::string &help,
T &value);
private:
virtual bool DoParseValue (const std::string &value);
virtual std::string DoGetType (void) const;
virtual std::string DoGetDefaultValue (void) const;
T *m_valuePtr;
};
static void PrintHelp (void);
typedef std::list<DefaultValueBase *> List;
static List *GetUserList (void);
static CommandDefaultValue g_help;
};
}//namespace ns3
namespace ns3 {
template <typename T>
void
CommandLine::AddArgValue (const std::string &name,
const std::string &help,
T &value)
{
DefaultValueBase *base =
new UserDefaultValue<T> (name, help, value);
GetUserList ()->push_back (base);
}
template <typename T>
CommandLine::UserDefaultValue<T>::UserDefaultValue (const std::string &name,
const std::string &help,
T &value)
: DefaultValueBase (name, help),
m_valuePtr (&value)
{
// we do not register in the DefaultValueList class on purpose.
}
template <typename T>
bool
CommandLine::UserDefaultValue<T>::DoParseValue (const std::string &value)
{
std::istringstream iss;
iss.str (value);
T v;
iss >> v;
*m_valuePtr = v;
return !iss.bad () && !iss.fail ();
}
template <typename T>
std::string
CommandLine::UserDefaultValue<T>::DoGetType (void) const
{
return "";
}
template <typename T>
std::string
CommandLine::UserDefaultValue<T>::DoGetDefaultValue (void) const
{
return "";
}
}//namespace ns3
#endif /* COMMAND_LINE_H */
+402
View File
@@ -0,0 +1,402 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "component-manager.h"
#include "uid-manager.h"
#include "singleton.h"
namespace ns3 {
// we redefine a UidManager type for the class id singleton below.
// otherwise, we would have to share the same id singleton instance
// with the Iids.
class CidManager : public UidManager
{};
ClassId::ClassId (std::string name)
: m_classId (Singleton<CidManager>::Get ()->Allocate (name))
{}
ClassId::ClassId (uint32_t classId)
: m_classId (classId)
{}
std::string
ClassId::GetName (void) const
{
return Singleton<CidManager>::Get ()->LookupByUid (m_classId);
}
bool operator == (const ClassId &a, const ClassId &b)
{
return a.m_classId == b.m_classId;
}
ComponentManager::ClassIdEntry::ClassIdEntry (ClassId classId)
: m_classId (classId)
{}
Ptr<Object>
ComponentManager::Create (ClassId classId)
{
Callback<Ptr<Object> > callback = DoGetCallback<empty,empty,empty,empty,empty> (classId);
return callback ();
}
CallbackBase *
ComponentManager::Lookup (ClassId classId)
{
List *list = Singleton<List>::Get ();
for (List::const_iterator i = list->begin (); i != list->end (); i++)
{
if (i->m_classId == classId)
{
return i->m_callback;
}
}
return 0;
}
ClassId
ComponentManager::LookupByName (std::string name)
{
return ClassId (Singleton<CidManager>::Get ()->LookupByName (name));
}
ClassId
ComponentManager::LookupByName (std::string name, bool *ok)
{
uint32_t cid = Singleton<CidManager>::Get ()->LookupByName (name);
if (cid == 0)
{
*ok = false;
}
else
{
*ok = true;
}
return ClassId (cid);
}
std::vector<ClassId>
ComponentManager::LookupByInterfaceId (InterfaceId iid)
{
std::vector<ClassId> classIdList;
List *list = Singleton<List>::Get ();
for (List::const_iterator i = list->begin (); i != list->end (); i++)
{
for (std::vector<const InterfaceId *>::const_iterator j = i->m_supportedInterfaces.begin ();
j != i->m_supportedInterfaces.end (); j++)
{
if (*(*j) == iid)
{
classIdList.push_back (i->m_classId);
break;
}
}
}
unique (classIdList.begin (), classIdList.end ());
return classIdList;
}
void
ComponentManager::Register (ClassId classId, CallbackBase *callback,
std::vector<const InterfaceId *> supportedInterfaces)
{
List *list = Singleton<List>::Get ();
struct ClassIdEntry entry = ClassIdEntry (classId);
entry.m_callback = callback;
bool foundObject = false;
for (std::vector<const InterfaceId *>::iterator i = supportedInterfaces.begin ();
i != supportedInterfaces.end (); i++)
{
if (*i == &Object::iid)
{
foundObject = true;
}
}
if (!foundObject)
{
supportedInterfaces.push_back (&Object::iid);
}
entry.m_supportedInterfaces = supportedInterfaces;
list->push_back (entry);
}
void
RegisterCallback (ClassId classId, CallbackBase *callback, std::vector<const InterfaceId *> supportedInterfaces)
{
return ComponentManager::Register (classId, callback, supportedInterfaces);
}
ClassIdDefaultValue::ClassIdDefaultValue (std::string name,
std::string help,
const InterfaceId &iid,
std::string defaultValue)
: DefaultValueBase (name, help),
m_defaultName (defaultValue),
m_name (defaultValue),
m_interfaceId (&iid)
{
DefaultValueList::Add (this);
}
ClassId
ClassIdDefaultValue::GetValue (void) const
{
return ComponentManager::LookupByName (m_name);
}
void
ClassIdDefaultValue::SetValue (ClassId classId)
{
m_name = classId.GetName ();
}
void
ClassIdDefaultValue::SetValue (std::string name)
{
m_name = name;
}
bool
ClassIdDefaultValue::DoParseValue (const std::string &value)
{
bool ok;
ClassId classId = ComponentManager::LookupByName (value, &ok);
if (!ok)
{
return false;
}
std::vector<ClassId> classIdList = ComponentManager::LookupByInterfaceId (*m_interfaceId);
for (std::vector<ClassId>::const_iterator i = classIdList.begin ();
i != classIdList.end (); i++)
{
if (*i == classId)
{
m_name = value;
return true;
}
}
return false;
}
std::string
ClassIdDefaultValue::DoGetType (void) const
{
std::vector<ClassId> classIdList = ComponentManager::LookupByInterfaceId (*m_interfaceId);
std::ostringstream oss;
oss << "(";
for (std::vector<ClassId>::const_iterator i = classIdList.begin ();
i != classIdList.end (); i++)
{
if (i != classIdList.begin ())
{
oss << "|";
}
oss << i->GetName ();
}
oss << ")";
return oss.str ();
}
std::string
ClassIdDefaultValue::DoGetDefaultValue (void) const
{
return m_name;
}
} // namespace ns3
#ifdef RUN_SELF_TESTS
#include "test.h"
#include "object.h"
namespace {
class B : public ns3::Object
{
public:
static const ns3::InterfaceId iid;
B ();
};
const ns3::InterfaceId B::iid = MakeInterfaceId ("B", Object::iid);
B::B ()
{
SetInterfaceId (B::iid);
}
class A : public ns3::Object
{
public:
static const ns3::ClassId cidZero;
static const ns3::ClassId cidOneBool;
static const ns3::ClassId cidOneUi32;
static const ns3::ClassId cidOther;
static const ns3::InterfaceId iid;
A ();
A (bool);
A (uint32_t);
bool m_zeroInvoked;
bool m_oneBoolInvoked;
bool m_oneUi32Invoked;
bool m_bool;
int m_ui32;
};
const ns3::ClassId A::cidZero = ns3::MakeClassId<A> ("A", A::iid);
const ns3::ClassId A::cidOneBool = ns3::MakeClassId <A,bool> ("ABool", A::iid);
const ns3::ClassId A::cidOneUi32 = ns3::MakeClassId <A,uint32_t> ("AUi32", A::iid);
const ns3::InterfaceId A::iid = ns3::MakeInterfaceId ("A", Object::iid);
A::A ()
: m_zeroInvoked (true),
m_oneBoolInvoked (false),
m_oneUi32Invoked (false)
{
SetInterfaceId (A::iid);
ns3::Ptr<B> b = ns3::Create<B> ();
AddInterface (b);
}
A::A (bool bo)
: m_zeroInvoked (false),
m_oneBoolInvoked (true),
m_oneUi32Invoked (false),
m_bool (bo)
{
SetInterfaceId (A::iid);
ns3::Ptr<B> b = ns3::Create<B> ();
AddInterface (b);
}
A::A (uint32_t i)
: m_zeroInvoked (false),
m_oneBoolInvoked (false),
m_oneUi32Invoked (true),
m_ui32 (i)
{
SetInterfaceId (A::iid);
ns3::Ptr<B> b = ns3::Create<B> ();
AddInterface (b);
}
class X : public A
{
public:
static const ns3::InterfaceId iid;
};
class C : public X
{
public:
static const ns3::InterfaceId iid;
};
class D : public C
{
public:
static const ns3::InterfaceId iid;
static const ns3::ClassId cid;
};
const ns3::InterfaceId X::iid = ns3::MakeInterfaceId ("X", A::iid);
const ns3::InterfaceId C::iid = ns3::MakeInterfaceId ("C", X::iid);
const ns3::InterfaceId D::iid = ns3::MakeInterfaceId ("D", C::iid);
const ns3::ClassId D::cid = ns3::MakeClassId<D> ("D", A::iid, X::iid, C::iid, D::iid);
}
namespace ns3 {
class ComponentManagerTest : public Test
{
public:
ComponentManagerTest ();
virtual bool RunTests (void);
};
ComponentManagerTest::ComponentManagerTest ()
: Test ("ComponentManager")
{}
bool
ComponentManagerTest::RunTests (void)
{
bool ok = true;
Ptr<A> a = 0;
a = ComponentManager::Create<A> (A::cidZero, A::iid);
if (a == 0 ||
!a->m_zeroInvoked)
{
ok = false;
}
a = ComponentManager::Create<A,bool> (A::cidOneBool, A::iid, true);
if (a == 0 ||
!a->m_oneBoolInvoked ||
!a->m_bool)
{
ok = false;
}
a = ComponentManager::Create<A,bool> (A::cidOneBool, A::iid, false);
if (a == 0 ||
!a->m_oneBoolInvoked ||
a->m_bool)
{
ok = false;
}
a = ComponentManager::Create<A,uint32_t> (A::cidOneUi32, A::iid, 10);
if (a == 0 ||
!a->m_oneUi32Invoked ||
a->m_ui32 != 10)
{
ok = false;
}
a = ComponentManager::Create<A> (A::cidOneUi32, A::iid, (uint32_t)10);
if (a == 0 ||
!a->m_oneUi32Invoked ||
a->m_ui32 != 10)
{
ok = false;
}
Ptr<B> b = ComponentManager::Create<B,uint32_t> (A::cidOneUi32, B::iid, 10);
if (b == 0)
{
ok = false;
}
return ok;
}
static ComponentManagerTest g_unknownManagerTest;
} // namespace ns3
#endif /* RUN_SELF_TESTS */
+686
View File
@@ -0,0 +1,686 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef COMPONENT_MANAGER_H
#define COMPONENT_MANAGER_H
#include <string>
#include <vector>
#include <stdint.h>
#include "callback.h"
#include "object.h"
#include "fatal-error.h"
#include "ptr.h"
#include "empty.h"
#include "default-value.h"
namespace {
// anonymous namespace for implementation code.
template <typename T, typename T1 = ns3::empty, typename T2 = ns3::empty,
typename T3 = ns3::empty, typename T4 = ns3::empty, typename T5 = ns3::empty>
struct ObjectMaker;
}
namespace ns3 {
/**
* \brief Unique Identifier for class constructors.
*
* Instances of this type must be allocated through
* the ns3::MakeClassId class.
*/
class ClassId
{
public:
/**
* \returns the symbolic name associated to this class id
*
* This name is the name which was associated to this class id
* by the ns3::Ns3UnknownManager::RegisterConstructor methods.
* This name is also the name which is expected to be input
* to ns3::UnknownManager::LookupByName.
*/
std::string GetName (void) const;
protected:
ClassId (std::string name);
private:
ClassId (uint32_t classId);
friend class ComponentManager;
friend ClassId AllocateClassId (std::string name);
friend bool operator == (const ClassId &a, const ClassId &b);
uint32_t m_classId;
};
/**
* \brief a class used to create ClassIds
*
*
*/
template <typename T, typename T1 = empty, typename T2 = empty,
typename T3 = empty, typename T4 = empty, typename T5 = empty>
class MakeClassId : public ClassId
{
public:
/**
* \param name name of ClassId
*
* Create a ClassId with specified name.
*/
MakeClassId (std::string name);
/**
* \param name name of ClassId
* \param iid interface id
*
* Create a ClassId with specified name. Register iid
* as a supported interface.
*/
MakeClassId (std::string name,
const InterfaceId &iid);
/**
* \param name name of ClassId
* \param iid0 interface id
* \param iid1 interface id
*
* Create a ClassId with specified name. Register iid0 and iid1
* as supported interfaces.
*/
MakeClassId (std::string name,
const InterfaceId &iid0,
const InterfaceId iid1);
/**
* \param name name of ClassId
* \param iid0 interface id
* \param iid1 interface id
* \param iid2 interface id
*
* Create a ClassId with specified name. Register iid0, iid1
* and iid2 as supported interfaces.
*/
MakeClassId (std::string name,
const InterfaceId &iid0,
const InterfaceId &iid1,
const InterfaceId &iid2);
/**
* \param name name of ClassId
* \param iid0 interface id
* \param iid1 interface id
* \param iid2 interface id
* \param iid3 interface id
*
* Create a ClassId with specified name. Register iid0, iid1
* iid2, and iid3 as supported interfaces.
*/
MakeClassId (std::string name,
const InterfaceId &iid0,
const InterfaceId &iid1,
const InterfaceId &iid2,
const InterfaceId &iid3);
/**
* \param name name of ClassId
* \param iid0 interface id
* \param iid1 interface id
* \param iid2 interface id
* \param iid3 interface id
* \param iid4 interface id
*
* Create a ClassId with specified name. Register iid0, iid1
* iid2, iid3, and iid4 as supported interfaces.
*/
MakeClassId (std::string name,
const InterfaceId &iid0,
const InterfaceId &iid1,
const InterfaceId &iid2,
const InterfaceId &iid3,
const InterfaceId &iid4);
private:
typedef ObjectMaker<T,T1,T2,T3,T4,T5> MakerType;
static Callback<Ptr<Object>,T1,T2,T3,T4,T5> m_callback;
void Register (const InterfaceId *array [], uint32_t n);
};
/**
* \brief Create any Interface
*
* This class keeps track of a set of ClassId, each
* of which uniquely identifies the constructor of an
* object which derives from the Interface base class.
* This class can also create an instance of any of
* the objects tracked through any of their tracked
* constructor/ClassId.
*/
class ComponentManager
{
public:
/**
* \param name the symbolic name to lookup
* \returns the ClassId associated to the input name.
*/
static ClassId LookupByName (std::string name);
static ClassId LookupByName (std::string name, bool *ok);
/**
* \param iid interface id to lookup
* \returns the list of ClassId which can be used to
* create objects which support the requested
* interface.
*
* Note that this method will not necessarily return the
* complete list of objects which support a given interface
* since dynamic aggregation of objects is not under
* the control of this class.
*/
static std::vector<ClassId> LookupByInterfaceId (InterfaceId iid);
/**
* \param classId class id of the constructor to invoke.
* \return a pointer to the instance created.
*
* Create an instance of the object identified by its
* ClassId. This method invokes the default constructor.
*/
static Ptr<Object> Create (ClassId classId);
/**
* \param classId class id of the constructor to invoke.
* \param a1 argument to pass to the constructor.
* \return a pointer to the instance created.
*
* Create an instance of the object identified by its
* ClassId.
*/
template <typename T1>
static Ptr<Object> Create (ClassId classId, T1 a1);
/**
* \param classId class id of the constructor to invoke.
* \param a1 first argument to pass to the constructor.
* \param a2 second argument to pass to the constructor.
* \return a pointer to the instance created.
*
* Create an instance of the object identified by its
* ClassId.
*/
template <typename T1, typename T2>
static Ptr<Object> Create (ClassId classId, T1 a1, T2 a2);
/**
* \param classId class id of the constructor to invoke.
* \param a1 first argument to pass to the constructor.
* \param a2 second argument to pass to the constructor.
* \param a3 third argument to pass to the constructor.
* \return a pointer to the instance created.
*
* Create an instance of the object identified by its
* ClassId.
*/
template <typename T1, typename T2, typename T3>
static Ptr<Object> Create (ClassId classId, T1 a1, T2 a2, T3 a3);
/**
* \param classId class id of the constructor to invoke.
* \param a1 first argument to pass to the constructor.
* \param a2 second argument to pass to the constructor.
* \param a3 third argument to pass to the constructor.
* \param a4 fourth argument to pass to the constructor.
* \return a pointer to the instance created.
*
* Create an instance of the object identified by its
* ClassId.
*/
template <typename T1, typename T2, typename T3, typename T4>
static Ptr<Object> Create (ClassId classId, T1 a1, T2 a2, T3 a3, T4 a4);
/**
* \param classId class id of the constructor to invoke.
* \param a1 first argument to pass to the constructor.
* \param a2 second argument to pass to the constructor.
* \param a3 third argument to pass to the constructor.
* \param a4 fourth argument to pass to the constructor.
* \param a5 fifth argument to pass to the constructor.
* \return a pointer to the instance created.
*
* Create an instance of the object identified by its
* ClassId.
*/
template <typename T1, typename T2, typename T3, typename T4, typename T5>
static Ptr<Object> Create (ClassId classId, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
/**
* \param classId class id of the constructor to invoke.
* \param iid interface id to query for
* \return a pointer to the instance created.
*
* Create an instance of the object identified by its
* ClassId, call QueryInterface on it, and return the
* result.
*/
template <typename T>
static Ptr<T> Create (ClassId classId, InterfaceId iid);
/**
* \param classId class id of the constructor to invoke.
* \param iid interface id to query for
* \param a1 first argument to pass to constructor
* \return a pointer to the instance created.
*
* Create an instance of the object identified by its
* ClassId, call QueryInterface on it, and return the
* result.
*/
template <typename T, typename T1>
static Ptr<T> Create (ClassId classId, InterfaceId iid, T1 a1);
/**
* \param classId class id of the constructor to invoke.
* \param iid interface id to query for
* \param a1 first argument to pass to constructor
* \param a2 second argument to pass to constructor
* \return a pointer to the instance created.
*
* Create an instance of the object identified by its
* ClassId, call QueryInterface on it, and return the
* result.
*/
template <typename T, typename T1, typename T2>
static Ptr<T> Create (ClassId classId, InterfaceId iid, T1 a1, T2 a2);
/**
* \param classId class id of the constructor to invoke.
* \param iid interface id to query for
* \param a1 first argument to pass to constructor
* \param a2 second argument to pass to constructor
* \param a3 third argument to pass to constructor
* \return a pointer to the instance created.
*
* Create an instance of the object identified by its
* ClassId, call QueryInterface on it, and return the
* result.
*/
template <typename T, typename T1, typename T2, typename T3>
static Ptr<T> Create (ClassId classId, InterfaceId iid, T1 a1, T2 a2, T3 a3);
/**
* \param classId class id of the constructor to invoke.
* \param iid interface id to query for
* \param a1 first argument to pass to constructor
* \param a2 second argument to pass to constructor
* \param a3 third argument to pass to constructor
* \param a4 fourth argument to pass to constructor
* \return a pointer to the instance created.
*
* Create an instance of the object identified by its
* ClassId, call QueryInterface on it, and return the
* result.
*/
template <typename T, typename T1, typename T2, typename T3, typename T4>
static Ptr<T> Create (ClassId classId, InterfaceId iid, T1 a1, T2 a2, T3 a3, T4 a4);
/**
* \param classId class id of the constructor to invoke.
* \param iid interface id to query for
* \param a1 first argument to pass to constructor
* \param a2 second argument to pass to constructor
* \param a3 third argument to pass to constructor
* \param a4 fourth argument to pass to constructor
* \param a5 fifth argument to pass to constructor
* \return a pointer to the instance created.
*
* Create an instance of the object identified by its
* ClassId, call QueryInterface on it, and return the
* result.
*/
template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
static Ptr<T> Create (ClassId classId, InterfaceId iid, T1 a1, T2 a2, T3 a3, T4 a4, T5);
private:
friend void RegisterCallback (ClassId classId, CallbackBase *callback,
std::vector<const InterfaceId *> supportedInterfaces);
static void Register (ClassId classId, CallbackBase *callback,
std::vector<const InterfaceId *> supportedInterfaces);
template <typename T1, typename T2,
typename T3, typename T4,
typename T5>
static Callback<Ptr<Object>,T1,T2,T3,T4,T5> DoGetCallback (ClassId classId);
struct ClassIdEntry {
ClassIdEntry (ClassId classId);
ClassId m_classId;
CallbackBase *m_callback;
std::vector<const InterfaceId *> m_supportedInterfaces;
};
typedef std::vector<struct ClassIdEntry> List;
static List *GetList (void);
static CallbackBase *Lookup (ClassId classId);
};
/**
* \brief a DefaultValue class to handle ClassIds
*
* This class provides the necessary glue to allow
* the Bind function and the command-line arguments
* to control the type of an object to create.
*/
class ClassIdDefaultValue : public DefaultValueBase
{
public:
/**
* \param name the name of this default value.
* \param help the help text associated to this default value
* \param iid the interface id which all objects created
* through this "default value" must support.
* \param defaultValue the name of the object to create
* by default.
*/
ClassIdDefaultValue (std::string name,
std::string help,
const InterfaceId &iid,
std::string defaultValue);
/**
* \returns the ClassId of the object selected by the user.
*/
ClassId GetValue (void) const;
/**
* \param classId the new ClassId selected.
*
* Override the currently-selected value.
*/
void SetValue (ClassId classId);
/**
* \param name the new object selected.
*
* Override the currently-selected value.
*/
void SetValue (std::string name);
private:
virtual bool DoParseValue (const std::string &value);
virtual std::string DoGetType (void) const;
virtual std::string DoGetDefaultValue (void) const;
std::string m_defaultName;
std::string m_name;
const InterfaceId *m_interfaceId;
};
} // namespace ns3
namespace {
template <typename T>
struct ObjectMaker<T,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty> {
static ns3::Ptr<ns3::Object>
MakeObject (void) {
return ns3::Create<T> ();
}
};
template <typename T, typename T1>
struct ObjectMaker<T,T1,ns3::empty,ns3::empty,ns3::empty,ns3::empty> {
static ns3::Ptr<ns3::Object>
MakeObject (T1 a1) {
return ns3::Create<T> (a1);
}
};
template <typename T, typename T1, typename T2>
struct ObjectMaker<T,T1,T2,ns3::empty,ns3::empty,ns3::empty> {
static ns3::Ptr<ns3::Object>
MakeObject (T1 a1, T2 a2) {
return ns3::Create<T> (a1, a2);
}
};
template <typename T, typename T1, typename T2, typename T3>
struct ObjectMaker<T,T1,T2,T3,ns3::empty,ns3::empty> {
static ns3::Ptr<ns3::Object>
MakeObject (T1 a1, T2 a2, T3 a3) {
return ns3::Create<T> (a1, a2, a3);
}
};
template <typename T, typename T1, typename T2, typename T3,
typename T4>
struct ObjectMaker<T,T1,T2,T3,T4,ns3::empty> {
static ns3::Ptr<ns3::Object>
MakeObject (T1 a1, T2 a2, T3 a3, T4 a4) {
return ns3::Create<T> (a1, a2, a3, a4);
}
};
template <typename T, typename T1, typename T2, typename T3,
typename T4, typename T5>
struct ObjectMaker {
static ns3::Ptr<ns3::Object>
MakeObject (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) {
return ns3::Create<T> (a1, a2, a3, a4, a5);
}
};
} // anonymous namespace
namespace ns3 {
void RegisterCallback (ClassId classId, ns3::CallbackBase *callback,
std::vector<const InterfaceId *> supportedInterfaces);
template <typename T, typename T1, typename T2,
typename T3, typename T4, typename T5>
void
MakeClassId<T,T1,T2,T3,T4,T5>::Register (const InterfaceId *array [], uint32_t n)
{
std::vector<const InterfaceId *> supportedInterfaces;
for (uint32_t i = 0; i < n; i++)
{
supportedInterfaces.push_back (array[i]);
}
RegisterCallback (*this, &m_callback, supportedInterfaces);
}
template <typename T, typename T1, typename T2,
typename T3, typename T4, typename T5>
MakeClassId<T,T1,T2,T3,T4,T5>::MakeClassId (std::string name)
: ClassId (name)
{
const InterfaceId *array[] = {};
Register (array, sizeof (array)/sizeof(InterfaceId *));
}
template <typename T, typename T1, typename T2,
typename T3, typename T4, typename T5>
MakeClassId<T,T1,T2,T3,T4,T5>::MakeClassId (std::string name,
const InterfaceId &iid)
: ClassId (name)
{
const InterfaceId *array[] = {&iid};
Register (array, sizeof (array)/sizeof(InterfaceId *));
}
template <typename T, typename T1, typename T2,
typename T3, typename T4, typename T5>
MakeClassId<T,T1,T2,T3,T4,T5>::MakeClassId (std::string name,
const InterfaceId &iid0,
const InterfaceId iid1)
: ClassId (name)
{
const InterfaceId *array[] = {&iid0, &iid1};
Register (array, sizeof (array)/sizeof(InterfaceId *));
}
template <typename T, typename T1, typename T2,
typename T3, typename T4, typename T5>
MakeClassId<T,T1,T2,T3,T4,T5>::MakeClassId (std::string name,
const InterfaceId &iid0,
const InterfaceId &iid1,
const InterfaceId &iid2)
: ClassId (name)
{
const InterfaceId *array[] = {&iid0, &iid1, &iid2};
Register (array, sizeof (array)/sizeof(InterfaceId *));
}
template <typename T, typename T1, typename T2,
typename T3, typename T4, typename T5>
MakeClassId<T,T1,T2,T3,T4,T5>::MakeClassId (std::string name,
const InterfaceId &iid0,
const InterfaceId &iid1,
const InterfaceId &iid2,
const InterfaceId &iid3)
: ClassId (name)
{
const InterfaceId *array[] = {&iid0, &iid1, &iid2, &iid3};
Register (array, sizeof (array)/sizeof(InterfaceId *));
}
template <typename T, typename T1, typename T2,
typename T3, typename T4, typename T5>
MakeClassId<T,T1,T2,T3,T4,T5>::MakeClassId (std::string name,
const InterfaceId &iid0,
const InterfaceId &iid1,
const InterfaceId &iid2,
const InterfaceId &iid3,
const InterfaceId &iid4)
: ClassId (name)
{
const InterfaceId *array[] = {&iid0, &iid1, iid2, &iid3, &iid4};
Register (array, sizeof (array)/sizeof(InterfaceId *));
}
template <typename T, typename T1, typename T2,
typename T3, typename T4, typename T5>
Callback<Ptr<Object>,T1,T2,T3,T4,T5> MakeClassId<T,T1,T2,T3,T4,T5>::m_callback =
MakeCallback (&MakeClassId::MakerType::MakeObject);
template <typename T1, typename T2,
typename T3, typename T4,
typename T5>
Callback<Ptr<Object>,T1,T2,T3,T4,T5>
ComponentManager::DoGetCallback (ClassId classId)
{
CallbackBase *callback = Lookup (classId);
if (callback == 0)
{
NS_FATAL_ERROR ("Invalid Class Id.");
}
Callback<Ptr<Object>,T1,T2,T3,T4,T5> reference;
reference.Assign (*callback);
return reference;
}
template <typename T1>
Ptr<Object>
ComponentManager::Create (ClassId classId, T1 a1)
{
Callback<Ptr<Object>,T1> callback = DoGetCallback<T1,empty,empty,empty,empty> (classId);
return callback (a1);
}
template <typename T1, typename T2>
Ptr<Object>
ComponentManager::Create (ClassId classId, T1 a1, T2 a2)
{
Callback<Ptr<Object>,T1,T2> callback = DoGetCallback<T1,T2,empty,empty,empty> (classId);
return callback (a1, a2);
}
template <typename T1, typename T2, typename T3>
Ptr<Object>
ComponentManager::Create (ClassId classId, T1 a1, T2 a2, T3 a3)
{
Callback<Ptr<Object>,T1,T2,T3> callback = DoGetCallback<T1,T2,T3,empty,empty> (classId);
return callback (a1, a2, a3);
}
template <typename T1, typename T2, typename T3, typename T4>
Ptr<Object>
ComponentManager::Create (ClassId classId, T1 a1, T2 a2, T3 a3, T4 a4)
{
Callback<Ptr<Object>,T1,T2,T3,T4> callback = DoGetCallback<T1,T2,T3,T4,empty> (classId);
return callback (a1, a2, a3, a4);
}
template <typename T1, typename T2, typename T3, typename T4, typename T5>
Ptr<Object>
ComponentManager::Create (ClassId classId, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
{
Callback<Ptr<Object>,T1,T2,T3,T4,T5> callback = DoGetCallback<T1,T2,T3,T4,T5> (classId);
return callback (a1, a2, a3, a4, a5);
}
template <typename T>
Ptr<T>
ComponentManager::Create (ClassId classId, InterfaceId iid)
{
Ptr<Object> obj = Create (classId);
Ptr<T> i = obj->QueryInterface<T> (iid);
return i;
}
template <typename T, typename T1>
Ptr<T>
ComponentManager::Create (ClassId classId, InterfaceId iid, T1 a1)
{
Ptr<Object> obj = Create (classId, a1);
Ptr<T> i = obj->QueryInterface<T> (iid);
return i;
}
template <typename T, typename T1, typename T2>
Ptr<T>
ComponentManager::Create (ClassId classId, InterfaceId iid, T1 a1, T2 a2)
{
Ptr<Object> obj = Create (classId, a1, a2);
Ptr<T> i = obj->QueryInterface<T> (iid);
return i;
}
template <typename T, typename T1, typename T2, typename T3>
Ptr<T>
ComponentManager::Create (ClassId classId, InterfaceId iid, T1 a1, T2 a2, T3 a3)
{
Ptr<Object> obj = Create (classId, a1, a2, a3);
Ptr<T> i = obj->QueryInterface<T> (iid);
return i;
}
template <typename T, typename T1, typename T2, typename T3, typename T4>
Ptr<T>
ComponentManager::Create (ClassId classId, InterfaceId iid, T1 a1, T2 a2, T3 a3, T4 a4)
{
Ptr<Object> obj = Create (classId, a1, a2, a3, a4);
Ptr<T> i = obj->QueryInterface<T> (iid);
return i;
}
template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
Ptr<T>
ComponentManager::Create (ClassId classId, InterfaceId iid, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
{
Ptr<Object> obj = Create (classId, a1, a2, a3, a4, a5);
Ptr<T> i = obj->QueryInterface<T> (iid);
return i;
}
} // namespace ns3
#endif /* COMPONENT_MANAGER_H */
+186
View File
@@ -0,0 +1,186 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2006 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include <list>
#include <utility>
#include <iostream>
#include "debug.h"
#include "assert.h"
#include "ns3/core-config.h"
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
namespace ns3 {
typedef std::list<std::pair <std::string, DebugComponent *> > ComponentList;
typedef std::list<std::pair <std::string, DebugComponent *> >::iterator ComponentListI;
static
ComponentList *GetComponentList (void)
{
static ComponentList components;
return &components;
}
static bool g_firstDebug = true;
void
DebugComponentEnableEnvVar (void)
{
#ifdef HAVE_GETENV
char *envVar = getenv("NS_DEBUG");
if (envVar == 0)
{
return;
}
std::string env = envVar;
std::string::size_type cur = 0;
std::string::size_type next = 0;
while (true)
{
next = env.find_first_of (";", cur);
std::string tmp = std::string (env, cur, next);
{
/* The following code is a workaround for a bug in the g++
* c++ string library. Its goal is to remove any trailing ';'
* from the string even though there should not be any in
* it. This code should be safe even if the bug is not there.
*/
std::string::size_type trailing = tmp.find_first_of (";");
tmp = tmp.substr (0, trailing);
}
if (tmp.size () == 0)
{
break;
}
bool found = false;
ComponentList *components = GetComponentList ();
for (ComponentListI i = components->begin ();
i != components->end ();
i++)
{
if (i->first.compare (tmp) == 0)
{
found = true;
i->second->Enable ();
break;
}
}
if (!found)
{
std::cout << "No debug component named=\"" << tmp << "\"" << std::endl;
}
if (next == std::string::npos)
{
break;
}
cur = next + 1;
if (cur >= env.size ())
{
break;
}
}
#endif
}
DebugComponent::DebugComponent (char const * name)
: m_isEnabled (false)
{
ComponentList *components = GetComponentList ();
for (ComponentListI i = components->begin ();
i != components->end ();
i++)
{
NS_ASSERT (i->first != name);
}
components->push_back (std::make_pair (name, this));
}
bool
DebugComponent::IsEnabled (void)
{
if (g_firstDebug)
{
DebugComponentEnableEnvVar ();
g_firstDebug = false;
}
return m_isEnabled;
}
void
DebugComponent::Enable (void)
{
m_isEnabled = true;
}
void
DebugComponent::Disable (void)
{
m_isEnabled = false;
}
void
DebugComponentEnable (char const *name)
{
ComponentList *components = GetComponentList ();
for (ComponentListI i = components->begin ();
i != components->end ();
i++)
{
if (i->first.compare (name) == 0)
{
i->second->Enable ();
break;
}
}
}
void
DebugComponentDisable (char const *name)
{
ComponentList *components = GetComponentList ();
for (ComponentListI i = components->begin ();
i != components->end ();
i++)
{
if (i->first.compare (name) == 0)
{
i->second->Disable ();
break;
}
}
}
void
DebugComponentPrintList (void)
{
ComponentList *components = GetComponentList ();
for (ComponentListI i = components->begin ();
i != components->end ();
i++)
{
std::cout << i->first << "=" << (i->second->IsEnabled ()?"enabled":"disabled") << std::endl;
}
}
}; // namespace ns3
+140
View File
@@ -0,0 +1,140 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2006 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef DEBUG_H
#define DEBUG_H
/**
* \defgroup debugging Debugging
* \brief Debugging functions and macros
*
* - DEBUG functionality: macros which allow developers to
* send information out on screen only in debugging builds.
* All debug messages are disabled by default. To enable
* selected debug messages, use the ns3::DebugComponentEnable
* function. Alternatively, you can use the NS_DEBUG
* environment variable to define a ';'-separated list of
* messages to enable. For example, NS_DEBUG=a;b;c;DAFD;GH
* would enable the components 'a', 'b', 'c', 'DAFD', and, 'GH'.
*/
namespace ns3 {
/**
* \param name a debug component name
* \ingroup debugging
*
* Enable the debugging output associated with that debug component.
* The debugging output can be later disabled with a call
* to ns3::DebugComponentDisable.
*/
void DebugComponentEnable (char const *name);
/**
* \param name a debug component name
* \ingroup debugging
*
* Disable the debugging output associated with that debug component.
* The debugging output can be later re-enabled with a call
* to ns3::DebugComponentEnable.
*/
void DebugComponentDisable (char const *name);
/**
* \ingroup debugging
* Print the list of debugging messages available.
*/
void DebugComponentPrintList (void);
class DebugComponent {
public:
DebugComponent (char const *name);
bool IsEnabled (void);
void Enable (void);
void Disable (void);
private:
bool m_isEnabled;
};
}; // namespace ns3
#ifdef NS3_DEBUG_ENABLE
#include <string>
#include <iostream>
/**
* \ingroup debugging
* \param name a string
*
* Define a Debug component with a specific name. This macro
* should be used at the top of every file in which you want
* to use the NS_DEBUG macro. This macro defines a new
* "debug component" which can be later selectively enabled
* or disabled with the ns3::DebugComponentEnable and
* ns3::DebugComponentDisable functions or with the NS_DEBUG
* environment variable.
*/
#define NS_DEBUG_COMPONENT_DEFINE(name) \
static ns3::DebugComponent g_debug = ns3::DebugComponent (name)
/**
* \ingroup debugging
* \param msg message to output
*
* Generate debugging output in the "debug component" of the
* current file. i.e., every call to NS_DEBUG from within
* a file implicitely generates out within the component
* defined with the NS_DEBUG_COMPONENT_DEFINE macro in the
* same file.
*/
#define NS_DEBUG(msg) \
do \
{ \
if (g_debug.IsEnabled ()) \
{ \
std::cout << msg << std::endl; \
} \
} \
while (false)
/**
* \ingroup debugging
* \param msg message to output
*
* Generate debugging output unconditionally in all
* debug builds.
*/
#define NS_DEBUG_UNCOND(msg) \
do \
{ \
std::cout << msg << std::endl; \
} \
while (false)
#else /* NS3_DEBUG_ENABLE */
#define NS_DEBUG_COMPONENT_DEFINE(name)
#define NS_DEBUG(x)
#define NS_DEBUG_UNCOND(msg)
#endif /* NS3_DEBUG_ENABLE */
#endif /* DEBUG_H */
+465
View File
@@ -0,0 +1,465 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INRIA
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "default-value.h"
#include "fatal-error.h"
namespace ns3 {
DefaultValueBase::DefaultValueBase (const std::string &name,
const std::string &help)
: m_name (name),
m_help (help)
{}
DefaultValueBase::~DefaultValueBase ()
{}
std::string
DefaultValueBase::GetName (void) const
{
return m_name;
}
std::string
DefaultValueBase::GetHelp (void) const
{
return m_help;
}
bool
DefaultValueBase::ParseValue (const std::string &value)
{
return DoParseValue (value);
}
std::string
DefaultValueBase::GetType (void) const
{
return DoGetType ();
}
std::string
DefaultValueBase::GetDefaultValue (void) const
{
return DoGetDefaultValue ();
}
DefaultValueList::Iterator
DefaultValueList::Begin (void)
{
return GetList ()->begin ();
}
DefaultValueList::Iterator
DefaultValueList::End (void)
{
return GetList ()->end ();
}
void
DefaultValueList::Remove (const std::string &name)
{
DefaultValueList::List *list = GetList ();
for (List::iterator i = list->begin (); i != list->end (); /* nothing */)
{
if ((*i)->GetName () == name)
{
i = list->erase (i);
}
else
{
i++;
}
}
}
void
DefaultValueList::Add (DefaultValueBase *defaultValue)
{
GetList ()->push_back (defaultValue);
}
DefaultValueList::List *
DefaultValueList::GetList (void)
{
static List list;
return &list;
}
enum BindStatus {
OK,
INVALID_VALUE,
NOT_FOUND
};
static
enum BindStatus
BindSafe (std::string name, std::string value)
{
for (DefaultValueList::Iterator i = DefaultValueList::Begin ();
i != DefaultValueList::End (); i++)
{
DefaultValueBase *cur = *i;
if (cur->GetName () == name)
{
if (!cur->ParseValue (value))
{
return INVALID_VALUE;
}
return OK;
}
}
return NOT_FOUND;
}
void
Bind (std::string name, std::string value)
{
switch (BindSafe (name, value)) {
case INVALID_VALUE:
NS_FATAL_ERROR ("Invalid value: "<<name<<"="<<value);
break;
case NOT_FOUND:
NS_FATAL_ERROR ("No registered DefaultValue=\"" << name << "\"");
break;
case OK:
break;
}
}
BooleanDefaultValue::BooleanDefaultValue (std::string name,
std::string help,
bool defaultValue)
: DefaultValueBase (name, help),
m_defaultValue (defaultValue),
m_value (defaultValue)
{
DefaultValueList::Add (this);
}
bool
BooleanDefaultValue::GetValue (void) const
{
return m_value;
}
bool
BooleanDefaultValue::DoParseValue (const std::string &value)
{
if (value.compare ("0") == 0 ||
value.compare ("f") == 0 ||
value.compare ("false") == 0 ||
value.compare ("FALSE") == 0)
{
m_value = false;
return true;
}
else if (value.compare ("1") == 0 ||
value.compare ("t") == 0 ||
value.compare ("true") == 0 ||
value.compare ("TRUE") == 0)
{
m_value = true;
return true;
}
else
{
return false;
}
}
std::string
BooleanDefaultValue::DoGetType (void) const
{
return "bool";
}
std::string
BooleanDefaultValue::DoGetDefaultValue (void) const
{
return m_defaultValue?"true":"false";
}
StringEnumDefaultValue::StringEnumDefaultValue (const std::string &name,
const std::string &help)
: DefaultValueBase (name, help),
m_oneDefault (false)
{
DefaultValueList::Add (this);
}
void
StringEnumDefaultValue::AddDefaultValue (const std::string &value)
{
if (m_oneDefault)
{
NS_FATAL_ERROR ("More than one default value registered: " << value);
}
m_oneDefault = true;
for (std::list<std::string>::iterator i = m_possibleValues.begin ();
i != m_possibleValues.end (); i++)
{
if (value == *i)
{
NS_FATAL_ERROR ("Value already exists: " << value);
}
}
m_possibleValues.push_back (value);
m_value = value;
m_defaultValue = value;
}
void
StringEnumDefaultValue::AddPossibleValue (const std::string &value)
{
for (std::list<std::string>::iterator i = m_possibleValues.begin ();
i != m_possibleValues.end (); i++)
{
if (value == *i)
{
NS_FATAL_ERROR ("Value already exists: " << value);
}
}
m_possibleValues.push_back (value);
}
std::string
StringEnumDefaultValue::GetValue (void) const
{
return m_value;
}
bool
StringEnumDefaultValue::DoParseValue (const std::string &value)
{
for (std::list<std::string>::iterator i = m_possibleValues.begin ();
i != m_possibleValues.end (); i++)
{
if (value == *i)
{
m_value = value;
return true;
}
}
return false;
}
std::string
StringEnumDefaultValue::DoGetType (void) const
{
std::string retval;
retval += "(";
for (std::list<std::string>::const_iterator i = m_possibleValues.begin ();
i != m_possibleValues.end (); i++)
{
if (i != m_possibleValues.begin ())
{
retval += "|";
}
retval += *i;
}
retval += ")";
return retval;
}
std::string
StringEnumDefaultValue::DoGetDefaultValue (void) const
{
return m_defaultValue;
}
CommandDefaultValue::CommandDefaultValue (const std::string &name,
const std::string &help,
Callback<void> cb)
: DefaultValueBase (name, help),
m_cb (cb)
{
DefaultValueList::Add (this);
}
bool
CommandDefaultValue::DoParseValue (const std::string &value)
{
m_cb ();
return true;
}
std::string
CommandDefaultValue::DoGetType (void) const
{
return "";
}
std::string
CommandDefaultValue::DoGetDefaultValue (void) const
{
return "";
}
}//namespace ns3
#ifdef RUN_SELF_TESTS
#include "test.h"
namespace ns3 {
enum MyEnum {
MY_ENUM_A,
MY_ENUM_B,
MY_ENUM_C,
MY_ENUM_D,
};
class DefaultValueTest : public Test
{
public:
DefaultValueTest ();
virtual bool RunTests (void);
};
DefaultValueTest::DefaultValueTest ()
: Test ("DefaultValue")
{}
bool
DefaultValueTest::RunTests (void)
{
bool ok = true;
BooleanDefaultValue a ("bool-a", "help a", true);
if (!a.GetValue ())
{
ok = false;
}
Bind ("bool-a", "false");
if (a.GetValue ())
{
ok = false;
}
BooleanDefaultValue b ("bool-b", "help b", false);
Bind ("bool-b", "true");
if (!b.GetValue ())
{
ok = false;
}
Bind ("bool-b", "0");
if (b.GetValue ())
{
ok = false;
}
Bind ("bool-b", "1");
if (!b.GetValue ())
{
ok = false;
}
Bind ("bool-b", "f");
if (b.GetValue ())
{
ok = false;
}
Bind ("bool-b", "t");
if (!b.GetValue ())
{
ok = false;
}
Bind ("bool-b", "false");
if (b.GetValue ())
{
ok = false;
}
if (BindSafe ("bool-b", "tr") != INVALID_VALUE)
{
ok = false;
}
IntegerDefaultValue<int> i ("test-i", "help-i", -1);
if (i.GetValue () != -1)
{
ok = false;
}
Bind ("test-i", "-2");
if (i.GetValue () != -2)
{
ok = false;
}
Bind ("test-i", "+2");
if (i.GetValue () != 2)
{
ok = false;
}
if (i.GetType () != "int32_t(-2147483648:2147483647)")
{
ok = false;
}
IntegerDefaultValue<uint32_t> ui32 ("test-ui32", "help-ui32", 10);
if (ui32.GetType () != "uint32_t(0:4294967295)")
{
ok = false;
}
IntegerDefaultValue<char> c ("test-c", "help-c", 10);
if (c.GetValue () != 10)
{
ok = false;
}
Bind ("test-c", "257");
EnumDefaultValue<enum MyEnum> e ("test-e", "help-e",
MY_ENUM_C, "C",
MY_ENUM_A, "A",
MY_ENUM_B, "B",
0, (void*)0);
if (e.GetValue () != MY_ENUM_C)
{
ok = false;
}
Bind ("test-e", "B");
if (e.GetValue () != MY_ENUM_B)
{
ok = false;
}
if (BindSafe ("test-e", "D") != INVALID_VALUE)
{
ok = false;
}
class MyEnumSubclass : public EnumDefaultValue<enum MyEnum>
{
public:
MyEnumSubclass ()
: EnumDefaultValue<enum MyEnum> ("test-e1", "help-e1",
MY_ENUM_B, "B",
MY_ENUM_A, "A",
0, (void*)0)
{
AddPossibleValue (MY_ENUM_C, "C");
AddPossibleValue (MY_ENUM_D, "D");
}
} e1 ;
if (e1.GetValue () != MY_ENUM_B)
{
ok = false;
}
Bind ("test-e1", "D");
if (e1.GetValue () != MY_ENUM_D)
{
ok = false;
}
DefaultValueList::Remove ("test-e1");
DefaultValueList::Remove ("test-e");
DefaultValueList::Remove ("bool-b");
DefaultValueList::Remove ("bool-a");
DefaultValueList::Remove ("test-i");
DefaultValueList::Remove ("test-c");
DefaultValueList::Remove ("test-ui32");
return ok;
}
static DefaultValueTest g_default_value_tests;
}//namespace ns3
#endif /* RUN_SELF_TESTS */
+531
View File
@@ -0,0 +1,531 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INRIA
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef DEFAULT_VALUE_H
#define DEFAULT_VALUE_H
#include <string>
#include <list>
#include "callback.h"
/**
* \defgroup config Simulation configuration
*
*/
namespace ns3 {
class DefaultValueBase
{
public:
virtual ~DefaultValueBase ();
std::string GetName (void) const;
std::string GetHelp (void) const;
// parse a matching parameter
// return true in case of success, false otherwise.
bool ParseValue (const std::string &value);
std::string GetType (void) const;
std::string GetDefaultValue (void) const;
protected:
DefaultValueBase (const std::string &name,
const std::string &help);
private:
virtual bool DoParseValue (const std::string &value) = 0;
virtual std::string DoGetType (void) const = 0;
virtual std::string DoGetDefaultValue (void) const = 0;
std::string m_name;
std::string m_help;
};
class DefaultValueList
{
public:
typedef std::list<DefaultValueBase *>::iterator Iterator;
static Iterator Begin (void);
static Iterator End (void);
static void Remove (const std::string &name);
static void Add (DefaultValueBase *defaultValue);
private:
typedef std::list<DefaultValueBase *> List;
static List *GetList (void);
};
/**
* \ingroup config
* \param name name of variable to bind
* \param value value to bind to the specified variable
*
* If the variable name does not match any existing
* variable or if the value is not compatible with
* the variable type, this function will abort
* at runtime and print an error message detailing
* which variable or value triggered the problem.
*/
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
* by ns3::Bind.
*/
class BooleanDefaultValue : public DefaultValueBase
{
public:
/**
* \param name name of variable
* \param help help text which explains the purpose
* and the semantics of this variable
* \param defaultValue the default value to assign
* to this variable.
*
* Unless the user invokes ns3::Bind with the right arguments,
* the GetValue method will return the default value. Otherwise,
* it will return the user-specified value.
*/
BooleanDefaultValue (std::string name,
std::string help,
bool defaultValue);
/**
* \returns the default value for this variable or a
* user-provided overriden variable.
*/
bool GetValue (void) const;
private:
virtual bool DoParseValue (const std::string &value);
virtual std::string DoGetType (void) const;
virtual std::string DoGetDefaultValue (void) const;
bool m_defaultValue;
bool m_value;
};
/**
* \brief An Integer variable for ns3::Bind
* \ingroup config
*
* Every instance of this type is automatically
* registered in the variable pool which is used
* by ns3::Bind.
*/
template <typename T>
class IntegerDefaultValue : public DefaultValueBase
{
public:
/**
* \param name the name of the variable
* \param help help text which explains the purpose
* and the semantics of this variable
* \param defaultValue the default value assigned
* to this variable
*
* By default, the set of allowed values is the entire range
* of values which can be stored and retrieved from the underlying
* type.
*/
IntegerDefaultValue (std::string name,
std::string help,
T defaultValue);
/**
* \param name the name of the variable
* \param help help text which explains the purpose
* and the semantics of this variable
* \param defaultValue the default value assigned to this
* variable
* \param minValue the minimum value which can be set
* in this variable
*/
IntegerDefaultValue (std::string name,
std::string help,
T defaultValue,
T minValue);
/**
* \param name the name of the variable
* \param help help text which explains the purpose
* and the semantics of this variable
* \param defaultValue the default value assigned to this
* variable
* \param minValue the minimum value which can be set
* in this variable
* \param maxValue the maximum value which can be set in this
* variable.
*/
IntegerDefaultValue (std::string name,
std::string help,
T defaultValue,
T minValue,
T maxValue);
void SetValue (T v);
T GetValue (void) const;
private:
virtual bool DoParseValue (const std::string &value);
virtual std::string DoGetType (void) const;
virtual std::string DoGetDefaultValue (void) const;
T m_defaultValue;
T m_minValue;
T m_maxValue;
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:
/**
* \param name The name of the variable
* \param help The help string
*/
StringEnumDefaultValue (const std::string &name,
const std::string &help);
/**
* \brief Add a default value to this enumeration of strings
* \param value The string to make the default for this
*/
void AddDefaultValue (const std::string &value);
/**
* \brief Add a possible value to accept for this default value
*/
void AddPossibleValue (const std::string &value);
/**
* \brief Get the value of this default value.
* \return The string that has been assigned to this default value, either by
* Bind() or by a command line setting
*/
std::string GetValue (void) const;
private:
virtual bool DoParseValue (const std::string &value);
virtual std::string DoGetType (void) const;
virtual std::string DoGetDefaultValue (void) const;
bool m_oneDefault;
std::list<std::string> m_possibleValues;
std::string m_defaultValue;
std::string m_value;
};
/**
* \brief An enum variable for ns3::Bind
* \ingroup config
*
* Every instance of this type is automatically
* registered in the variable pool which is used
* by ns3::Bind.
*/
template <typename T>
class EnumDefaultValue : public DefaultValueBase
{
public:
/**
* \param name the name of this variable
* \param help help text which explains the purpose
* and the semantics of this variable
* \param defaultValue the default value assigned to this
* variable unless it is overriden with ns3::Bind
* \param defaultValueString the string which represents
* the default value which should be used by ns3::Bind
*
* This method takes a variable number of arguments. The list of
* arguments is terminated by the pair of values 0 and (void *)0.
* Each pair of extra argument is assumed to be of the form
* (enum value, string representing enum value). If ns3::Bind
* is invoked on this variable, it will check that the user-provided
* values are within the set of values specified in this constructor.
*
* Typical useage of this method will look like this:
* \code
* enum MyEnum {
* MY_ENUM_A,
* MY_ENUM_B,
* MY_ENUM_C,
* };
* // set default value to be "B".
* static EnumDefaultValue<enum MyEnum>
* g_myDefaultValue ("my", "my help",
* MY_ENUM_B, "B",
* MY_ENUM_A, "A",
* MY_ENUM_C, "C",);
* 0, (void*)0);
* \endcode
* Note that to ensure portability to 64 bit systems, make sure that
* the last element in the variable list of arguments is (void *)0.
*/
EnumDefaultValue (const std::string &name, const std::string &help,
T defaultValue, const char *defaultValueString,
...);
void AddPossibleValue (T value, const std::string &valueString);
/**
* \returns the default value or any other value specified by the
* user with ns3::Bind
*/
T GetValue (void);
/**
* \param value the new default value.
*/
void SetValue (T value);
private:
virtual bool DoParseValue (const std::string &value);
virtual std::string DoGetType (void) const;
virtual std::string DoGetDefaultValue (void) const;
typedef std::list<std::pair<T,std::string> > PossibleValues;
T m_defaultValue;
PossibleValues m_possibleValues;
T m_value;
};
/**
* \brief Class used to call a certain function during the configuration of the
* simulation
* \ingroup config
*/
class CommandDefaultValue : public DefaultValueBase
{
public:
CommandDefaultValue (const std::string &name,
const std::string &help,
Callback<void> cb);
private:
virtual bool DoParseValue (const std::string &value);
virtual std::string DoGetType (void) const;
virtual std::string DoGetDefaultValue (void) const;
Callback<void> m_cb;
};
}//namespace ns3
#include "type-name.h"
#include "assert.h"
#include <sstream>
#include <stdarg.h>
#include <limits>
namespace ns3 {
/**************************************************************
**************************************************************/
template <typename T>
IntegerDefaultValue<T>::IntegerDefaultValue (std::string name,
std::string help,
T defaultValue)
: DefaultValueBase (name, help),
m_defaultValue (defaultValue),
m_minValue (std::numeric_limits<T>::min ()),
m_maxValue (std::numeric_limits<T>::max ()),
m_value (defaultValue)
{
DefaultValueList::Add (this);
NS_ASSERT (m_minValue < m_maxValue);
}
template <typename T>
IntegerDefaultValue<T>::IntegerDefaultValue (std::string name,
std::string help,
T defaultValue,
T minValue)
: DefaultValueBase (name, help),
m_defaultValue (defaultValue),
m_minValue (minValue),
m_maxValue (std::numeric_limits<T>::max ()),
m_value (defaultValue)
{
DefaultValueList::Add (this);
NS_ASSERT (m_minValue < m_maxValue);
NS_ASSERT (m_defaultValue <= m_maxValue &&
m_defaultValue >= m_minValue);
}
template <typename T>
IntegerDefaultValue<T>::IntegerDefaultValue (std::string name,
std::string help,
T defaultValue,
T minValue,
T maxValue)
: DefaultValueBase (name, help),
m_defaultValue (defaultValue),
m_minValue (minValue),
m_maxValue (maxValue),
m_value (defaultValue)
{
DefaultValueList::Add (this);
NS_ASSERT (m_minValue < m_maxValue);
NS_ASSERT (m_defaultValue <= m_maxValue &&
m_defaultValue >= m_minValue);
}
template <typename T>
void
IntegerDefaultValue<T>::SetValue (T v)
{
NS_ASSERT (v <= m_maxValue &&
v >= m_minValue);
m_value = v;
}
template <typename T>
T
IntegerDefaultValue<T>::GetValue (void) const
{
return m_value;
}
template <typename T>
bool
IntegerDefaultValue<T>::DoParseValue (const std::string &value)
{
std::istringstream iss;
iss.str (value);
iss >> m_value;
if (m_value > m_maxValue ||
m_value < m_minValue)
{
return false;
}
return !iss.bad () && !iss.fail ();
}
template <typename T>
std::string
IntegerDefaultValue<T>::DoGetType (void) const
{
std::ostringstream oss;
oss << TypeNameGet<T> () << "("
<< m_minValue << ":"
<< m_maxValue << ")";
return oss.str ();
}
template <typename T>
std::string
IntegerDefaultValue<T>::DoGetDefaultValue (void) const
{
std::ostringstream oss;
oss << m_defaultValue;
return oss.str ();
}
/**************************************************************
**************************************************************/
template <typename T>
EnumDefaultValue<T>::EnumDefaultValue (const std::string &name, const std::string &help,
T defaultValue, const char *defaultValueString,
...)
: DefaultValueBase (name, help),
m_defaultValue (defaultValue),
m_value (defaultValue)
{
AddPossibleValue (defaultValue, defaultValueString);
va_list list;
va_start (list, defaultValueString);
while (true)
{
T v = (T) va_arg (list, int);
const char *str = va_arg (list, const char *);
if (v == 0 && str == 0)
{
break;
}
AddPossibleValue (v, str);
}
DefaultValueList::Add (this);
}
template <typename T>
void
EnumDefaultValue<T>::AddPossibleValue (T value, const std::string &valueString)
{
m_possibleValues.push_back (std::make_pair (value, valueString));
}
template <typename T>
T
EnumDefaultValue<T>::GetValue (void)
{
return m_value;
}
template <typename T>
void
EnumDefaultValue<T>::SetValue (T value)
{
m_value = value;
}
template <typename T>
bool
EnumDefaultValue<T>::DoParseValue (const std::string &value)
{
for (typename PossibleValues::iterator i = m_possibleValues.begin ();
i != m_possibleValues.end (); i++)
{
if (value == i->second)
{
m_value = i->first;
return true;
}
}
return false;
}
template <typename T>
std::string
EnumDefaultValue<T>::DoGetType (void) const
{
std::string retval;
retval += "(";
for (typename PossibleValues::const_iterator i = m_possibleValues.begin ();
i != m_possibleValues.end (); i++)
{
if (i != m_possibleValues.begin ())
{
retval += "|";
}
retval += i->second;
}
retval += ")";
return retval;
}
template <typename T>
std::string
EnumDefaultValue<T>::DoGetDefaultValue (void) const
{
for (typename PossibleValues::const_iterator i = m_possibleValues.begin ();
i != m_possibleValues.end (); i++)
{
if (i->first == m_defaultValue)
{
return i->second;
}
}
// cannot happen theoretically.
NS_ASSERT (false);
return ""; // quiet compiler
}
}//namespace ns3
#endif /* DEFAULT_VALUE_H */
+8
View File
@@ -0,0 +1,8 @@
#ifndef EMPTY_H
#define EMPTY_H
namespace ns3 {
class empty {};
}
#endif /* EMPTY_H */
+48
View File
@@ -0,0 +1,48 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2006 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef FATAL_ERROR_H
#define FATAL_ERROR_H
#include "assert.h"
#include <iostream>
/**
* \defgroup error Error
* \brief fatal error handling
*
* \param msg message to output when this macro is hit.
*
* When this macro is hit at runtime, the user-specified
* error message is output and the program is halted by calling
* the ns3::AssertBreakpoint function. This macro is enabled
* unconditionally in all builds, including debug and optimized
* builds.
*/
#define NS_FATAL_ERROR(msg) \
do \
{ \
std::cout << msg << std::endl; \
ns3::AssertBreakpoint (); \
} \
while (false)
#endif /* FATAL_ERROR_H */
+419
View File
@@ -0,0 +1,419 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INRIA, Gustavo Carneiro
*
* 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
*
* Authors: Gustavo Carneiro <gjcarneiro@gmail.com>,
* Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "object.h"
#include "assert.h"
#include "singleton.h"
#include "uid-manager.h"
#include <vector>
namespace {
class IidManager : public ns3::UidManager
{};
class IidTree
{
public:
void SetParent (uint16_t child, const uint16_t *parent);
uint16_t LookupParent (uint16_t child);
private:
std::vector<const uint16_t *> m_parents;
};
void
IidTree::SetParent (uint16_t child, const uint16_t *parent)
{
m_parents.resize (child+1);
m_parents[child] = parent;
}
uint16_t
IidTree::LookupParent (uint16_t child)
{
NS_ASSERT (child < m_parents.size ());
return *(m_parents[child]);
}
} // anonymous namespace
namespace ns3 {
InterfaceId::InterfaceId (uint16_t iid)
: m_iid (iid)
{}
InterfaceId::~InterfaceId ()
{}
InterfaceId
InterfaceId::LookupByName (std::string name)
{
uint32_t uid = Singleton<IidManager>::Get ()->LookupByName (name);
NS_ASSERT (uid != 0 && uid <= 0xffff);
return InterfaceId (uid);
}
InterfaceId
InterfaceId::LookupParent (InterfaceId iid)
{
return Singleton<IidTree>::Get ()->LookupParent (iid.m_iid);
}
bool operator == (const InterfaceId &a, const InterfaceId &b)
{
return a.m_iid == b.m_iid;
}
bool operator != (const InterfaceId &a, const InterfaceId &b)
{
return a.m_iid != b.m_iid;
}
InterfaceId
MakeInterfaceId (std::string name, const InterfaceId &parent)
{
uint32_t uid = Singleton<IidManager>::Get ()->Allocate (name);
NS_ASSERT (uid <= 0xffff);
InterfaceId iid = uid;
Singleton<IidTree>::Get ()->SetParent (iid.m_iid, &parent.m_iid);
return iid;
}
InterfaceId
MakeObjectInterfaceId (void)
{
InterfaceId iid = Singleton<IidManager>::Get ()->Allocate ("Object");
Singleton<IidTree>::Get ()->SetParent (iid.m_iid, &iid.m_iid);
return iid;
}
const InterfaceId Object::iid = MakeObjectInterfaceId ();
Object::Object ()
: m_count (1),
m_iid (Object::iid),
m_disposed (false),
m_next (this)
{}
Object::~Object ()
{
m_next = 0;
}
Ptr<Object>
Object::DoQueryInterface (InterfaceId iid) const
{
NS_ASSERT (Check ());
const Object *currentObject = this;
do {
NS_ASSERT (currentObject != 0);
InterfaceId cur = currentObject->m_iid;
while (cur != iid && cur != Object::iid)
{
cur = InterfaceId::LookupParent (cur);
}
if (cur == iid)
{
return const_cast<Object *> (currentObject);
}
currentObject = currentObject->m_next;
} while (currentObject != this);
return 0;
}
void
Object::Dispose (void)
{
Object *current = this;
do {
NS_ASSERT (current != 0);
NS_ASSERT (!current->m_disposed);
current->DoDispose ();
current->m_disposed = true;
current = current->m_next;
} while (current != this);
}
void
Object::AddInterface (Ptr<Object> o)
{
NS_ASSERT (!m_disposed);
NS_ASSERT (!o->m_disposed);
NS_ASSERT (Check ());
NS_ASSERT (o->Check ());
Object *other = PeekPointer (o);
Object *next = m_next;
m_next = other->m_next;
other->m_next = next;
NS_ASSERT (Check ());
NS_ASSERT (o->Check ());
}
void
Object::SetInterfaceId (InterfaceId iid)
{
NS_ASSERT (Check ());
m_iid = iid;
}
void
Object::DoDispose (void)
{
NS_ASSERT (!m_disposed);
}
bool
Object::Check (void) const
{
return (m_count > 0);
}
void
Object::MaybeDelete (void) const
{
// First, check if any of the attached
// Object has a non-zero count.
const Object *current = this;
do {
NS_ASSERT (current != 0);
if (current->m_count != 0)
{
return;
}
current = current->m_next;
} while (current != this);
// all attached objects have a zero count so,
// we can delete all attached objects.
current = this;
const Object *end = this;
do {
NS_ASSERT (current != 0);
Object *next = current->m_next;
delete current;
current = next;
} while (current != end);
}
} // namespace ns3
#ifdef RUN_SELF_TESTS
#include "test.h"
namespace {
class BaseA : public ns3::Object
{
public:
static const ns3::InterfaceId iid;
BaseA ()
{
SetInterfaceId (BaseA::iid);
}
virtual void Dispose (void) {}
};
class DerivedA : public BaseA
{
public:
static const ns3::InterfaceId iid;
DerivedA (int v)
{
SetInterfaceId (DerivedA::iid);
}
virtual void Dispose (void) {
BaseA::Dispose ();
}
};
const ns3::InterfaceId BaseA::iid =
ns3::MakeInterfaceId ("BaseA", Object::iid);
const ns3::InterfaceId DerivedA::iid =
ns3::MakeInterfaceId ("DerivedA", BaseA::iid);;
class BaseB : public ns3::Object
{
public:
static const ns3::InterfaceId iid;
BaseB ()
{
SetInterfaceId (BaseB::iid);
}
virtual void Dispose (void) {}
};
class DerivedB : public BaseB
{
public:
static const ns3::InterfaceId iid;
DerivedB (int v)
{
SetInterfaceId (DerivedB::iid);
}
virtual void Dispose (void) {
BaseB::Dispose ();
}
};
const ns3::InterfaceId BaseB::iid =
ns3::MakeInterfaceId ("BaseB", Object::iid);
const ns3::InterfaceId DerivedB::iid =
ns3::MakeInterfaceId ("DerivedB", BaseB::iid);;
} // namespace anonymous
namespace ns3 {
class ObjectTest : public Test
{
public:
ObjectTest ();
virtual bool RunTests (void);
};
ObjectTest::ObjectTest ()
: Test ("Object")
{}
bool
ObjectTest::RunTests (void)
{
bool ok = true;
Ptr<BaseA> baseA = Create<BaseA> ();
if (baseA->QueryInterface<BaseA> (BaseA::iid) != baseA)
{
ok = false;
}
if (baseA->QueryInterface<BaseA> (DerivedA::iid) != 0)
{
ok = false;
}
if (baseA->QueryInterface<DerivedA> (DerivedA::iid) != 0)
{
ok = false;
}
baseA = Create<DerivedA> (10);
if (baseA->QueryInterface<BaseA> (BaseA::iid) != baseA)
{
ok = false;
}
if (baseA->QueryInterface<BaseA> (DerivedA::iid) != baseA)
{
ok = false;
}
if (baseA->QueryInterface<DerivedA> (DerivedA::iid) == 0)
{
ok = false;
}
baseA = Create<BaseA> ();
Ptr<BaseB> baseB = Create<BaseB> ();
Ptr<BaseB> baseBCopy = baseB;
baseA->AddInterface (baseB);
if (baseA->QueryInterface<BaseA> (BaseA::iid) == 0)
{
ok = false;
}
if (baseA->QueryInterface<DerivedA> (DerivedA::iid) != 0)
{
ok = false;
}
if (baseA->QueryInterface<BaseB> (BaseB::iid) == 0)
{
ok = false;
}
if (baseA->QueryInterface<DerivedB> (DerivedB::iid) != 0)
{
ok = false;
}
if (baseB->QueryInterface<BaseB> (BaseB::iid) == 0)
{
ok = false;
}
if (baseB->QueryInterface<DerivedB> (DerivedB::iid) != 0)
{
ok = false;
}
if (baseB->QueryInterface<BaseA> (BaseA::iid) == 0)
{
ok = false;
}
if (baseB->QueryInterface<DerivedA> (DerivedA::iid) != 0)
{
ok = false;
}
if (baseBCopy->QueryInterface<BaseA> (BaseA::iid) == 0)
{
ok = false;
}
baseA = Create<DerivedA> (1);
baseB = Create<DerivedB> (1);
baseBCopy = baseB;
baseA->AddInterface (baseB);
if (baseA->QueryInterface<DerivedB> (DerivedB::iid) == 0)
{
ok = false;
}
if (baseA->QueryInterface<BaseB> (BaseB::iid) == 0)
{
ok = false;
}
if (baseB->QueryInterface<DerivedA> (DerivedA::iid) == 0)
{
ok = false;
}
if (baseB->QueryInterface<BaseA> (BaseA::iid) == 0)
{
ok = false;
}
if (baseBCopy->QueryInterface<DerivedA> (DerivedA::iid) == 0)
{
ok = false;
}
if (baseBCopy->QueryInterface<BaseA> (BaseA::iid) == 0)
{
ok = false;
}
if (baseB->QueryInterface<DerivedB> (DerivedB::iid) == 0)
{
ok = false;
}
if (baseB->QueryInterface<BaseB> (BaseB::iid) == 0)
{
ok = false;
}
baseA = Create<BaseA> ();
baseB = Create<BaseB> ();
baseA->AddInterface (baseB);
baseA = 0;
baseA = baseB->QueryInterface<BaseA> (BaseA::iid);
return ok;
}
static ObjectTest g_interfaceObjectTests;
} // namespace ns3
#endif /* RUN_SELF_TESTS */
+194
View File
@@ -0,0 +1,194 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INRIA, Gustavo Carneiro
*
* 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
*
* Authors: Gustavo Carneiro <gjcarneiro@gmail.com>,
* Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef OBJECT_H
#define OBJECT_H
#include <stdint.h>
#include <string>
#include "ptr.h"
namespace ns3 {
/**
* \brief a unique identifier for an interface.
*
* Instances of this class can be created only through
* calls to ns3::MakeInterfaceId.
*
* Note: This class is quite similar to COM's UUIDs.
*/
class InterfaceId
{
public:
/**
* \param name the name of the requested interface
* \returns the unique id associated with the requested
* name.
*
* This method cannot fail: it will crash if the input
* name is not a valid interface name.
*/
static InterfaceId LookupByName (std::string name);
/**
* \param iid a unique id
* \returns the parent of the requested id, as registered
* by ns3::MakeInterfaceId.
*
* This method cannot fail: it will crash if the input
* id is not a valid interface id.
*/
static InterfaceId LookupParent (InterfaceId iid);
~InterfaceId ();
private:
InterfaceId (uint16_t iid);
friend InterfaceId MakeInterfaceId (std::string name, const InterfaceId &parent);
friend InterfaceId MakeObjectInterfaceId (void);
friend bool operator == (const InterfaceId &a, const InterfaceId &b);
friend bool operator != (const InterfaceId &a, const InterfaceId &b);
uint16_t m_iid;
};
/**
* \param name of the new InterfaceId to create.
* \param parent the "parent" of the InterfaceId to create.
* \returns a new InterfaceId
* \relates InterfaceId
*
* Every InterfaceId is a child of another InterfaceId. The
* top-most InterfaceId is Object::iid and its parent is
* itself.
*/
InterfaceId
MakeInterfaceId (std::string name, const InterfaceId &parent);
/**
* \brief a base class which provides memory management and object aggregation
*
* Note: This base class is quite similar in spirit to IUnknown in COM or
* BonoboObject in Bonobo: it provides three main methods: Ref, Unref and
* QueryInterface.
*/
class Object
{
public:
static const InterfaceId iid;
Object ();
virtual ~Object ();
/**
* Increment the reference count. This method should not be called
* by user code. Object instances are expected to be used in conjunction
* of the Ptr template which would make calling Ref unecessary and
* dangerous.
*/
inline void Ref (void) const;
/**
* Decrement the reference count. This method should not be called
* by user code. Object instances are expected to be used in conjunction
* of the Ptr template which would make calling Ref unecessary and
* dangerous.
*/
inline void Unref (void) const;
/**
* \param iid the interface requested
* \returns a pointer to the requested interface or zero if it could not be found.
*
*/
template <typename T>
Ptr<T> QueryInterface (InterfaceId iid) const;
/**
* Run the DoDispose methods of this object and all the
* objects aggregated to it.
* After calling this method, the object is expected to be
* totally unusable except for the Ref and Unref methods.
* It is an error to call Dispose twice on the same object
* instance
*/
void Dispose (void);
/**
* \param other another object pointer
*
* This method aggregates the two objects together: after this
* method returns, it becomes possible to call QueryInterface
* on one to get the other, and vice-versa.
*/
void AddInterface (Ptr<Object> other);
protected:
/**
* \param iid an InterfaceId
*
* Every subclass which defines a new InterfaceId for itself
* should register this InterfaceId by calling this method
* from its constructor.
*/
void SetInterfaceId (InterfaceId iid);
/**
* This method is called by Object::Dispose.
* Subclasses are expected to override this method and chain
* up to their parent's implementation once they are done.
*/
virtual void DoDispose (void);
private:
Ptr<Object> DoQueryInterface (InterfaceId iid) const;
bool Check (void) const;
void MaybeDelete (void) const;
mutable uint32_t m_count;
InterfaceId m_iid;
bool m_disposed;
Object *m_next;
};
} // namespace ns3
namespace ns3 {
void
Object::Ref (void) const
{
m_count++;
}
void
Object::Unref (void) const
{
NS_ASSERT (Check ());
m_count--;
if (m_count == 0)
{
MaybeDelete ();
}
}
template <typename T>
Ptr<T>
Object::QueryInterface (InterfaceId iid) const
{
Ptr<Object> found = DoQueryInterface (iid);
if (found != 0)
{
return Ptr<T> (dynamic_cast<T *> (PeekPointer (found)));
}
return 0;
}
} // namespace ns3
#endif /* OBJECT_H */
+311
View File
@@ -0,0 +1,311 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2005,2006 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "ptr.h"
#ifdef RUN_SELF_TESTS
#include "test.h"
#include "callback.h"
#include "object.h"
namespace ns3 {
class NoCount : public Object
{
public:
NoCount (Callback<void> cb);
~NoCount ();
void Nothing (void) const;
private:
Callback<void> m_cb;
};
NoCount::NoCount (Callback<void> cb)
: m_cb (cb)
{}
NoCount::~NoCount ()
{
m_cb ();
}
void
NoCount::Nothing () const
{}
class PtrTest : Test
{
public:
PtrTest ();
virtual ~PtrTest ();
virtual bool RunTests (void);
private:
void DestroyNotify (void);
Ptr<NoCount> CallTest (Ptr<NoCount> p);
Ptr<NoCount> const CallTestConst (Ptr<NoCount> const p);
uint32_t m_nDestroyed;
};
PtrTest::PtrTest ()
: Test ("Ptr")
{}
PtrTest::~PtrTest ()
{}
void
PtrTest::DestroyNotify (void)
{
m_nDestroyed++;
}
Ptr<NoCount>
PtrTest::CallTest (Ptr<NoCount> p)
{
return p;
}
Ptr<NoCount> const
PtrTest::CallTestConst (Ptr<NoCount> const p)
{
return p;
}
bool
PtrTest::RunTests (void)
{
bool ok = true;
Callback<void> cb = MakeCallback (&PtrTest::DestroyNotify, this);
m_nDestroyed = false;
{
Ptr<NoCount> p = Create<NoCount> (cb);
}
if (m_nDestroyed != 1)
{
ok = false;
}
m_nDestroyed = 0;
{
Ptr<NoCount> p;
p = Create<NoCount> (cb);
p = p;
}
if (m_nDestroyed != 1)
{
ok = false;
}
m_nDestroyed = 0;
{
Ptr<NoCount> p1;
p1 = Create<NoCount> (cb);
Ptr<NoCount> p2 = p1;
}
if (m_nDestroyed != 1)
{
ok = false;
}
m_nDestroyed = 0;
{
Ptr<NoCount> p1;
p1 = Create<NoCount> (cb);
Ptr<NoCount> p2;
p2 = p1;
}
if (m_nDestroyed != 1)
{
ok = false;
}
m_nDestroyed = 0;
{
Ptr<NoCount> p1;
p1 = Create<NoCount> (cb);
Ptr<NoCount> p2 = Create<NoCount> (cb);
p2 = p1;
}
if (m_nDestroyed != 2)
{
ok = false;
}
m_nDestroyed = 0;
{
Ptr<NoCount> p1;
p1 = Create<NoCount> (cb);
Ptr<NoCount> p2;
p2 = Create<NoCount> (cb);
p2 = p1;
}
if (m_nDestroyed != 2)
{
ok = false;
}
m_nDestroyed = 0;
{
Ptr<NoCount> p1;
p1 = Create<NoCount> (cb);
p1 = Create<NoCount> (cb);
}
if (m_nDestroyed != 2)
{
ok = false;
}
m_nDestroyed = 0;
{
Ptr<NoCount> p1;
{
Ptr<NoCount> p2;
p1 = Create<NoCount> (cb);
p2 = Create<NoCount> (cb);
p2 = p1;
}
if (m_nDestroyed != 1)
{
ok = false;
}
}
if (m_nDestroyed != 2)
{
ok = false;
}
m_nDestroyed = 0;
{
Ptr<NoCount> p1;
{
Ptr<NoCount> p2;
p1 = Create<NoCount> (cb);
p2 = Create<NoCount> (cb);
p2 = CallTest (p1);
}
if (m_nDestroyed != 1)
{
ok = false;
}
}
if (m_nDestroyed != 2)
{
ok = false;
}
{
Ptr<NoCount> p1;
Ptr<NoCount> const p2 = CallTest (p1);
Ptr<NoCount> const p3 = CallTestConst (p1);
Ptr<NoCount> p4 = CallTestConst (p1);
Ptr<NoCount const> p5 = p4;
//p4 = p5; You cannot make a const pointer be a non-const pointer.
// but if you use const_pointer_cast, you can.
p4 = const_pointer_cast<NoCount> (p5);
p5 = p1;
Ptr<NoCount> p;
if (p == 0)
{}
if (p != 0)
{}
if (0 == p)
{}
if (0 != p)
{}
if (p)
{}
if (!p)
{}
}
m_nDestroyed = 0;
{
NoCount *raw;
{
Ptr<NoCount> p = Create<NoCount> (cb);
{
Ptr<NoCount const> p1 = p;
}
raw = GetPointer (p);
p = 0;
}
if (m_nDestroyed != 0)
{
ok = false;
}
delete raw;
}
m_nDestroyed = 0;
{
Ptr<NoCount> p = Create<NoCount> (cb);
const NoCount *v1 = PeekPointer (p);
NoCount *v2 = PeekPointer (p);
v1->Nothing ();
v2->Nothing ();
}
if (m_nDestroyed != 1)
{
ok = false;
}
{
Ptr<Object> p0 = Create<NoCount> (cb);
Ptr<NoCount> p1 = Create<NoCount> (cb);
if (p0 == p1)
{
ok = false;
}
if (p0 != p1)
{
}
else
{
ok = false;
}
}
{
Ptr<NoCount> p = Create<NoCount> (cb);
Callback<void> callback = MakeCallback (&NoCount::Nothing, p);
callback ();
}
{
Ptr<const NoCount> p = Create<NoCount> (cb);
Callback<void> callback = MakeCallback (&NoCount::Nothing, p);
callback ();
}
#if 0
// as expected, fails compilation.
{
Ptr<const Object> p = Create<NoCount> (cb);
Callback<void> callback = MakeCallback (&NoCount::Nothing, p);
}
#endif
return ok;
}
PtrTest g_ptr_test;
}; // namespace ns3
#endif /* RUN_SELF_TESTS */

Some files were not shown because too many files have changed in this diff Show More