Compare commits

..

491 Commits

Author SHA1 Message Date
Tom Henderson 1e70c7ac38 add Joe Kopena to AUTHORS list 2008-02-16 11:51:58 -08:00
Tom Henderson bf0d4e7154 avoid infinite recursion in Tcp callback (bug 131) 2008-02-15 19:54:34 -08:00
Mathieu Lacage e8fc6ec946 fix doxygen. 2008-02-15 20:53:07 +01:00
Mathieu Lacage be2b52ac8f update version number 2008-02-15 20:37:34 +01:00
Mathieu Lacage 7bb06e0661 initial release notes 2008-02-15 20:37:19 +01:00
Mathieu Lacage b56cad3cbc bug 133: automate RandomVariable memory management. 2008-02-15 20:03:48 +01:00
Mathieu Lacage 5bec43f720 fix bug 137: Make Ipv4Address (uint32_t) constructor explicit. patch by Gustavo. 2008-02-15 19:14:35 +01:00
Gustavo J. A. M. Carneiro ee5f2a5475 Make the OLSR routing protocol priority higher, not lower, than static routing.
The reason for this change is related to the fact that sockets now send
broadcast (255.255.255.255) packets as subnetwork directed broadcasts.  With
wireless OLSR nodes with only a single interface, in order for OLSR to hear
each other's broadcasts they all need to be in the same network.  On the other
hand, if the nodes are all in the same network then the static routing module
will mistakenly believe it has direct conectivity to all other nodes, thereby
bypassing OLSR completely.
2008-02-14 19:01:01 +00:00
Gustavo J. A. M. Carneiro 2806d0edbe Add support for tracing the OLSR routing table size. 2008-02-14 18:55:11 +00:00
Gustavo J. A. M. Carneiro 85cbeccd3e Check for malformed trace paths that do not start with '/'. 2008-02-14 18:15:26 +00:00
Gustavo J. A. M. Carneiro 147510bb00 Make Packet::RemoveTag behave as documented (bug #139) 2008-02-14 17:48:15 +00:00
Raj Bhattacharjea cdc9002e41 Fix TCP server socket connection notification (part of bug 132) 2008-02-13 09:55:15 -05:00
Gustavo J. A. M. Carneiro f8ae534480 A couple more OLSR bug fixes 2008-02-13 18:23:20 +00:00
Gustavo J. A. M. Carneiro c6f3793178 OLSR: code cleanup, more extensive logging, many bug fixes. Should also handle multiple interfaces better, now. 2008-02-13 17:44:05 +00:00
Gustavo J. A. M. Carneiro 96451fdb37 Make the OLSR example a bit more complete, adding a 5th node, to exercise 3-hop routing. 2008-02-13 17:42:08 +00:00
Gustavo J. A. M. Carneiro feb47b3bb1 Fix broadcast packet reception for locally bound sockets (bug #136) 2008-02-13 17:37:43 +00:00
Gustavo J. A. M. Carneiro 4f02439cb1 Add the IPv4 header before deciding whether to drop packets. Closes bug #135. 2008-02-11 14:46:44 +00:00
Gustavo J. A. M. Carneiro a14e1de6cc The message "Unable to determine outbound interface. No default route set"
should not be fatal; just return false instead.
2008-02-10 22:34:04 +00:00
Gustavo J. A. M. Carneiro a30e3a7e94 Upgrade WAF to version 1.3.2 2008-02-10 13:19:07 +00:00
Gustavo J. A. M. Carneiro 450f9db5c6 RandomWalk2dMobilityModel changed name to RandomWalkMobilityModel (typo or intentional?) 2008-02-10 11:51:53 +00:00
Gustavo J. A. M. Carneiro eca7dc5b27 Make sequence-number.h a public header file (because it is included by another public header, tcp-header.h) 2008-02-09 18:37:58 +00:00
Craig Dowell b4c23f8ebf branch merge 2008-02-06 10:03:46 -08:00
Craig Dowell dd8985b92d further ns-3-obj changes 2008-02-06 10:03:09 -08:00
Gustavo J. A. M. Carneiro 9fcd20505c Move TcpSocket's m_retxEvent.Cancel() to ~TcpSocket(), so that it is executed by all possible code paths leading up to a TcpSocket deallocation. 2008-02-06 17:11:56 +00:00
Raj Bhattacharjea a142d30a9d Merge 2008-02-05 15:30:16 -05:00
Raj Bhattacharjea c3658bd810 Slight refactor of TCP code so two way connections don't bug out 2008-02-05 15:29:17 -05:00
Raj Bhattacharjea 6e7d9062cb Patch for bug 130 from Gustavo 2008-02-05 09:54:32 -05:00
Tom Henderson a6438d91b4 some more edits to the front part of the tutorial 2008-02-04 23:09:07 -08:00
Craig Dowell d2d16360c1 fix instances of stale names 2008-02-04 19:17:45 -08:00
Craig Dowell 3b277785c0 object model section of tutorial needed to be rewritten due to ns-3-object changes. 2008-02-04 19:04:01 -08:00
Craig Dowell c3719a2eca tutorial now agrees with ns3-object changes 2008-02-04 12:56:08 -08:00
Craig Dowell 3b58cf8c0e half of example describing how to plumb in new model without plumbing 2008-02-04 12:27:18 -08:00
Tom Henderson b390f1ef73 Further alignment of simple-point-to-point.cc with ns-2/simple.tcl (add TCP) 2008-02-03 14:34:10 -08:00
Gustavo J. A. M. Carneiro 02fd903228 OLSR: remove the 'Link tuple has no corresponding neighbor tuple' assertion; it happens now because MID messages may occasionally not arrive in time, but it's normal. 2008-02-03 19:09:35 +00:00
Gustavo J. A. M. Carneiro 52ca0dd3f6 merge 2008-02-03 19:05:37 +00:00
Gustavo J. A. M. Carneiro 6a874b283c OLSR: get main address of the peer from the UDP source address and the 'interface association' table; this way the UDP source address need not be the same as the main address. 2008-02-03 18:50:55 +00:00
Gustavo J. A. M. Carneiro fd238f3e40 Backed out changeset 055ff23aa034 (Tom does not like it turns out OLSR does not need it) 2008-02-03 18:29:25 +00:00
Tom Henderson 438036550f Fix tutorial TOC 2008-02-02 20:46:04 -08:00
Tom Henderson a0e14bd523 formatting cleanup 2008-02-02 15:52:54 -08:00
Tom Henderson c8a76b7dd5 typos and formatting of Introduction section 2008-02-01 21:31:15 -08:00
Gustavo J. A. M. Carneiro c86c3ce16d UDP sockets are fixed, remove the hack and note. 2008-02-01 19:37:27 +00:00
Gustavo J. A. M. Carneiro dd48772c9e Fix UDP source address, make it honor Bind(). 2008-02-01 19:29:56 +00:00
Gustavo J. A. M. Carneiro 53833582b7 Some more udp socket debug messages 2008-02-01 18:40:14 +00:00
Gustavo J. A. M. Carneiro f262b76a41 Put back the simulation time in 30 seconds, else we generate huge trace files. 2008-02-01 18:39:37 +00:00
Gustavo J. A. M. Carneiro 441e17174d Add more debug info to olsr routing table 2008-02-01 18:24:39 +00:00
Gustavo J. A. M. Carneiro defd58bc77 In OLSR agent, work around newly introduced bug in UDP sockets prenting Bind from working as e.g. Linux. Add note explaining what's wrong. 2008-02-01 18:07:45 +00:00
Gustavo J. A. M. Carneiro 38f2897c29 Fix OLSR example: don't add static routes, increase simulation time to 300 seconds. 2008-02-01 17:17:24 +00:00
Gustavo J. A. M. Carneiro d9d019c5d4 Unbreak ParameterLogger 2008-02-01 15:16:44 +00:00
Gustavo J. A. M. Carneiro f23152d7a7 Start the Olsr agent (accidentally removed during last code refactoring) 2008-02-01 14:05:59 +00:00
Mathieu Lacage d625837eb9 merge with HEAD 2008-02-01 08:50:03 +01:00
Mathieu Lacage cecd35e20b AddInterface -> AggregateObject 2008-01-31 22:23:46 +01:00
Mathieu Lacage 5ade799440 QueryInterface -> GetObject 2008-01-31 22:11:03 +01:00
Mathieu Lacage 2786b195ee merge with HEAD again 2008-01-31 21:58:13 +01:00
Mathieu Lacage 5f5518e05b merge with HEAD 2008-01-30 17:20:55 +01:00
Mathieu Lacage bd33305e5b remove dependency on Callbacks from Ptr test code 2008-01-30 15:33:48 +01:00
Tom Henderson aa8bd8a8ba some more tutorial updates 2008-01-27 10:58:22 -08:00
Tom Henderson 84cdad7f7d fix optimized build 2008-01-26 06:01:45 -08:00
Tom Henderson 3c38ca5a1b Fix uninitialized member 2008-01-25 15:41:47 -08:00
Tom Henderson ffaf3e7d91 Merge TCP implementation (raj/ns-3-tcp) 2008-01-25 15:21:40 -08:00
Tom Henderson a81a6fc0ec Add chapter on callbacks to the tutorial 2008-01-25 11:58:17 -08:00
Raj Bhattacharjea 6c3559792c Added in ns-3-tcp (second try) 2008-01-25 13:57:38 -05:00
Tom Henderson 6292ead1f7 add hyperlinks to wiki, Doxygen 2008-01-19 21:03:18 -08:00
Tom Henderson 9a15ceadf6 Split tutorial.texi into multiple files; some work on the tracing section 2008-01-19 20:58:01 -08:00
Mathieu Lacage f61e9a9941 interface-id -> type-id 2008-01-16 10:27:07 +01:00
Craig Dowell 21a113f38f Added tag release ns-3.0.10 for changeset b5bf2588cde2 2008-01-15 16:01:26 -08:00
Craig Dowell 4f3bd6f9dd bump version and add release notes 2008-01-15 15:43:00 -08:00
Gustavo J. A. M. Carneiro d2c80f4d1a Print the correct type in the callback assign error message (instead of Ptr<const CallbackImplBase>) 2008-01-15 15:14:24 +00:00
Mathieu Lacage 2949d86908 add an extra link to the PHY model paper 2008-01-15 13:29:41 +01:00
Mathieu Lacage 0fcbdbf0fe fix doxygen warnings 2008-01-15 13:27:45 +01:00
Mathieu Lacage 1dc22a9e8f merge with head 2008-01-15 12:58:27 +01:00
Mathieu Lacage 5c769d2d24 iid -> tid 2008-01-15 12:44:09 +01:00
Mathieu Lacage a2e63b7f0b iid (void) -> GetTypeId (void) 2008-01-15 12:43:07 +01:00
Mathieu Lacage 44c33f1618 InterfaceId -> TypeId 2008-01-15 12:36:22 +01:00
Mathieu Lacage 4730d7087f merge with HEAD 2008-01-15 12:07:31 +01:00
Tom Henderson 3b31a0234e Doxygen organization 2008-01-10 07:31:40 -08:00
Tom Henderson cac5b2ca97 Missing subsection text 2008-01-11 08:31:38 -08:00
Tom Henderson 3b08f13bf3 remove executable bit from file mode 2008-01-09 22:17:02 -08:00
Tom Henderson e51bb180d4 Fix bug 125 (make helper function non-virtual) 2008-01-09 22:09:21 -08:00
Gustavo J. A. M. Carneiro 4e97b6b47c Document the iid parameter of OnOffApplication. 2008-01-08 17:45:57 +00:00
Gustavo J. A. M. Carneiro ed6ee71ded Don't print 'Entering directory xxx' when running waf --shell; it is misleading. 2008-01-08 14:06:49 +00:00
Craig Dowell 6c69295696 fix node and up 2008-01-07 16:48:53 -08:00
Craig Dowell fb72939392 figures 2008-01-07 16:29:54 -08:00
Craig Dowell b61692f121 interfaces 2008-01-07 16:03:32 -08:00
Mathieu Lacage 9ff2549315 copy the packet before sending it down or up 2008-01-07 18:20:18 +01:00
Gustavo J. A. M. Carneiro 3a4eb97315 Add a --valgrind WAF option (bug #124) 2008-01-03 14:14:17 +00:00
Mathieu Lacage 4f58be6548 replace ComponentManager::Create and ClassId with InterfaceId::CreateObjest and InterfaceId 2008-01-03 11:39:45 +01:00
Mathieu Lacage 33bd62d32f typo 2008-01-03 11:37:23 +01:00
Mathieu Lacage c547c88e89 use NS_OBJECT_ENSURE_REGISTERED and fix off-by-one in IidManager::GetRegistered 2008-01-03 11:37:09 +01:00
Mathieu Lacage 2a4dcce444 add NS_OBJECT_ENSURE_REGISTERED 2008-01-03 11:30:02 +01:00
Mathieu Lacage b41d008223 go to the next element in search loop 2008-01-03 11:29:35 +01:00
Mathieu Lacage a144ad9a1e work around weird compiler warning/error. 2008-01-03 10:37:50 +01:00
Mathieu Lacage 93be0562cc check constructor with reference arguments 2008-01-03 10:15:41 +01:00
Mathieu Lacage 64bb988613 a replacement for ClassIdDefaultValue 2008-01-03 09:10:40 +01:00
Mathieu Lacage 3fcff1b1b3 add InterfaceId::HasConstructor 2008-01-03 09:10:23 +01:00
Mathieu Lacage 6150ba4860 make the internal InterfaceId constructor explicit 2008-01-03 08:42:04 +01:00
Mathieu Lacage 676307027c add support to browse the list of existing InterfaceId 2008-01-03 08:41:15 +01:00
Mathieu Lacage 976f16c4d9 get rid of MakeInterfaceId 2008-01-03 08:34:31 +01:00
Mathieu Lacage b88e90fec3 add 'factory' support to InterfaceId 2008-01-02 15:54:53 +01:00
Mathieu Lacage 2103459845 merge with callback improvements. 2008-01-02 13:40:37 +01:00
Mathieu Lacage 348eb1e187 Make the CallbackBase class more useful than it was. 2008-01-02 13:39:56 +01:00
Mathieu Lacage 1fb6ad5488 rewrite interface id metadata 2008-01-02 12:24:25 +01:00
Mathieu Lacage 328aa2cc45 remove some remnants from the iid-a-variable era. 2008-01-02 11:08:11 +01:00
Mathieu Lacage 2deb2ea0f0 add some separation markers 2008-01-02 10:57:25 +01:00
Mathieu Lacage bc1ab2d79b replace static const Interface iid; with static InterfaceId iid (void); 2008-01-02 10:33:39 +01:00
Mathieu Lacage f3e77eea3d fix bug 122: get rid of duplicate argument to QueryInterface 2008-01-02 09:25:31 +01:00
Mathieu Lacage 6b0e717a19 add CreateObject<> to instanciate subclasses of the Object base class. Replaces Create<>. 2008-01-02 09:09:24 +01:00
Tom Henderson 906a9748b5 fix bug in PacketSink 2007-12-30 19:36:44 -08:00
Tom Henderson 414c33ffc9 remove const qualifier from uint16_t 2007-12-28 06:50:47 -08:00
Tom Henderson 77f8c5cbf2 Fix small typo 2007-12-26 20:08:48 -08:00
Tom Henderson 3f5d7030cb update doc/tracing.h to Ptr<Packet> 2007-12-26 13:02:09 -08:00
Tom Henderson c53c3afd46 back out doc/tutorial.h (not yet) 2007-12-26 11:41:47 -08:00
Tom Henderson 33fd7f0c67 Doxygen for internet-node.h 2007-12-26 11:39:52 -08:00
Mathieu Lacage 853f0a13e9 add missing copyright/license header 2007-12-26 15:41:48 +01:00
Mathieu Lacage 9569ad645b fix bug 98 2007-12-25 11:09:15 +01:00
Gustavo J. A. M. Carneiro 3a98117aa5 Remove ghost declaration of function AllocateClassId. 2007-12-22 18:46:43 +00:00
Gustavo J. A. M. Carneiro 42092bc91e Don't include the 'global-route-manager-impl.h' private header from the public header 'candidate-queue.h'. 2007-12-20 15:19:57 +00:00
Mathieu Lacage 2d6f46dfa8 forward only packets for ourselves. 2007-12-19 13:24:52 +01:00
Mathieu Lacage f1f400bcee it is possible to receive packets which are not tagged. ignore them rather than crash. 2007-12-19 13:24:30 +01:00
Mathieu Lacage a6e289c8ef ensure m_listener is initialized properly 2007-12-19 13:22:55 +01:00
Gustavo J. A. M. Carneiro a83ec513a1 const fixes (new GCC 4.2 warning) 2007-12-17 14:53:14 +00:00
Mathieu Lacage f043a8789c doxygen 2007-12-17 13:41:51 +01:00
Mathieu Lacage 30bbef4b14 add a few comments here and there 2007-12-17 13:27:22 +01:00
Mathieu Lacage 26fb62c748 more doxygen 2007-12-17 13:20:02 +01:00
Mathieu Lacage 77c0e85775 add some doxygen 2007-12-17 13:07:41 +01:00
Tom Henderson ac45276835 update release_steps.txt 2007-12-15 15:08:30 -08:00
Tom Henderson cfa242a6a5 Added tag release ns-3.0.9 for changeset 4db981a0d9eb 2007-12-15 14:58:58 -08:00
Tom Henderson 26599981a0 bump VERSION and finish RELEASE_NOTES 2007-12-15 14:01:36 -08:00
Tom Henderson 8fe2191d04 Repair doxygen errors 2007-12-15 13:59:33 -08:00
Tom Henderson 35b4c6c6b8 add internal keyword to udp-impl documentation 2007-12-15 13:52:00 -08:00
Mathieu Lacage e42ccef4a7 fix optimized build 2007-12-15 11:58:14 +01:00
Mathieu Lacage 8449139061 fix optimized build 2007-12-15 11:57:43 +01:00
Craig Dowell 16e7e60cab packet pointer police patrolled product preventing presence of prior pattern proactively 2007-12-14 16:05:37 -08:00
Mathieu Lacage c53988d01e success heuristic was inverted. 2007-12-14 17:42:16 +01:00
Mathieu Lacage 1fea8b38fc fix optimized build 2007-12-14 17:26:18 +01:00
Mathieu Lacage 7d6cd9ae7c some debugging. Max rate test was inverted. 2007-12-14 15:43:52 +01:00
Mathieu Lacage bd70c33606 avoid uninitialized variables. 2007-12-14 15:18:14 +01:00
Craig Dowell f2a0ca2b0e put updated tutorial.texi in doc directory 2007-12-13 23:50:16 -08:00
Raj Bhattacharjea 282543b759 Add uint8_t* based API for sockets 2007-12-13 09:40:21 -05:00
Mathieu Lacage 15748575d8 implement the MRR portion of AMRR 2007-12-13 15:07:08 +01:00
Mathieu Lacage cc9655af45 return the computed rate 2007-12-13 15:04:11 +01:00
Mathieu Lacage 465bf1c10a implement AMRR for true. 2007-12-13 14:43:56 +01:00
Mathieu Lacage eb1200a2cd AMRR rate control algorithm 2007-12-13 13:00:02 +01:00
Mathieu Lacage c1a71e53f9 the meat of the onoe rate control algorithm. 2007-12-13 09:26:20 +01:00
Mathieu Lacage f5fe661c13 Onoe rate control 2007-12-13 08:39:08 +01:00
Mathieu Lacage f42e5c4814 use the new MacStation::Report*Failed methods. 2007-12-12 13:36:16 +01:00
Mathieu Lacage 135a4ab58c add MacStation::ReportFinal* methods for onoe rate control model 2007-12-12 13:17:04 +01:00
Mathieu Lacage b192207132 introduce a low latency parameter for rate control algorithms 2007-12-12 12:03:38 +01:00
Mathieu Lacage 3464e84e90 initial release notes for upcoming release 2007-12-12 11:03:35 +01:00
Mathieu Lacage a0ee98cb4b add legend support to gnuplot output 2007-12-12 09:33:22 +01:00
Mathieu Lacage 01d7a64670 add legend support to gnuplot output 2007-12-12 09:33:22 +01:00
Mathieu Lacage cbafcb5aa6 updated doxygen 2007-12-11 17:53:54 +01:00
Mathieu Lacage b604bf2d7a estimation delay and jitter 2007-12-11 17:48:09 +01:00
Mathieu Lacage 05efca8430 merge with HEAD 2007-12-11 15:54:58 +01:00
Mathieu Lacage 007f125e46 add support for gnuplot error bars 2007-12-11 15:49:23 +01:00
Mathieu Lacage 83dd618e5b add tracing support to PacketSink 2007-12-11 14:03:20 +01:00
Mathieu Lacage ffc992893f fix small typo 2007-12-11 14:03:02 +01:00
Mathieu Lacage b04e3d6cd6 add tx packet trace support 2007-12-11 13:51:18 +01:00
Mathieu Lacage 5e19f9707b add application tracing support 2007-12-11 13:51:03 +01:00
Mathieu Lacage 457d07a50f make Packet::AddTag a const method 2007-12-11 13:42:09 +01:00
Mathieu Lacage 3262a4e103 add application tracing support 2007-12-11 13:51:03 +01:00
Mathieu Lacage df27c80c72 merge with HEAD 2007-12-12 08:15:04 +01:00
Tom Henderson bc54e34375 Doxygen the SocketFactory classes 2007-12-11 23:02:47 -08:00
Mathieu Lacage 49deb08b81 make Packet::AddTag a const method 2007-12-11 13:42:09 +01:00
Mathieu Lacage b8fbe8341f merge with HEAD 2007-12-11 10:25:34 +01:00
Tom Henderson 07e46fb8aa fix bug 113 on m_node parameter for GlobalRouter 2007-12-09 21:39:28 -08:00
Gustavo J. A. M. Carneiro 0ee86b72fb New waf snapshot; move the ns3 library back to the top build dir (the 'lib' was only a workaround for a waf problem); allow --enable-modules on a per build run basis. 2007-12-09 14:39:07 +00:00
Mathieu Lacage b54c43b966 the check was not really inverted after all. Damned. 2007-12-07 10:06:29 +01:00
Mathieu Lacage 1b82e5cba7 make sure we never set a negative duration 2007-12-07 09:51:59 +01:00
Mathieu Lacage 8a825ee775 merge with HEAD 2007-12-07 08:43:55 +01:00
Mathieu Lacage c91b667c13 use contrib gnuplot code 2007-12-07 08:41:52 +01:00
Mathieu Lacage 32611749b2 Gnuplot output class for contrib module 2007-12-06 13:30:26 +01:00
Federico Maguolo dd9e29c425 Avoid integer division 2007-12-06 13:12:27 +01:00
Gustavo J. A. M. Carneiro 8debe6ef1d Create a new contrib module; move event-garbage-collector.{h,cc} to the contrib module. 2007-12-06 11:05:17 +00:00
Gustavo J. A. M. Carneiro bab56b0d88 Add support for publishing ns3 headers in a subdir of ns3/ (we probably won't be needing this, but since it was implemented it might as well be commited, in case we ever need it) 2007-12-05 11:51:10 +00:00
Mathieu Lacage 0b43b4fdc2 the bool check was inverted. reported by Federico Maguolo. 2007-11-29 16:28:16 +01:00
Mathieu Lacage 210fb3539c fix typo 2007-11-29 16:03:01 +01:00
Mathieu Lacage 026f3f2aef MaxSeconds -> Simulator::GetMaximumSimulationTime 2007-11-29 15:59:31 +01:00
Mathieu Lacage 9b5d0a50f7 ConnectTo -> Attach 2007-11-29 15:50:15 +01:00
Mathieu Lacage d3df13225d remove references to WifiNetDeviceFactory 2007-11-29 15:45:12 +01:00
Mathieu Lacage fb2ebab793 speed vector -> velocity vector 2007-11-29 01:03:41 +01:00
Mathieu Lacage 2f71efe6a7 merge 2007-11-29 01:01:46 +01:00
Mathieu Lacage 7813d6fdd7 fix typo due to Packet & -> Ptr<Packet> change 2007-11-29 00:59:00 +01:00
Gustavo J. A. M. Carneiro 8ce92e1bc2 Fix bad Message Size value in OLSR headers (which prevented wireshark from decoding most OLSR packets). 2007-11-27 10:36:27 +00:00
Federico Maguolo 9316a5c23f re-use the CaculateTxDuration method where it is needed. 2007-11-23 10:29:27 +01:00
Federico Maguolo 64684b6b71 Improve the accuracy of 802.11a tx duration calculations. 2007-11-23 10:23:55 +01:00
Mathieu Lacage f133bfaf9f avoid memory leak 2007-11-23 11:36:16 +01:00
Mathieu Lacage 3f174e0bd0 avoid confusion between code and uncoded rates. 2007-11-22 16:40:35 +01:00
Mathieu Lacage 39a0e3b29c fix a small style issue 2007-11-22 16:07:45 +01:00
Mathieu Lacage ac8e86643e initialize variable 2007-11-22 16:06:05 +01:00
Mathieu Lacage 6a51ea96c0 make sure that the retry bit is correctly initialized 2007-11-22 15:00:32 +01:00
Mathieu Lacage 94e2d9059a merge obvious fix from mainline 2007-11-22 14:52:57 +01:00
Mathieu Lacage 85c67ca048 the intent was to always send data if maxbytes is zero. 2007-11-22 14:50:59 +01:00
Mathieu Lacage 99a5a8370f port to Ptr<Packet> branch 2007-11-22 14:27:22 +01:00
Mathieu Lacage 284ebcc23f merge with Ptr<Packet> branch 2007-11-22 10:44:48 +01:00
Mathieu Lacage c156f29c86 merge 2007-11-22 10:30:29 +01:00
Mathieu Lacage e075fcd4f3 bug 104: add a method to retrive the maximum simulation time. 2007-11-21 15:54:34 +01:00
Mathieu Lacage 49a8c459a8 simplify the parsing logic and remove buggy comment and code. 2007-11-21 14:14:12 +01:00
Mathieu Lacage 1e45a4c9f5 bug 91: add print-list support to NS_LOG env var. 2007-11-21 14:06:46 +01:00
Mathieu Lacage dd825831c7 bug 109: improve the doxygen documentation for RandomVariable 2007-11-21 13:36:47 +01:00
Mathieu Lacage 1b17161758 code layout fix 2007-11-21 11:12:02 +01:00
Mathieu Lacage 908971e48b improve log output 2007-11-21 11:11:27 +01:00
Mathieu Lacage ca76e83370 add WifiPhy::GetDevice 2007-11-21 11:11:05 +01:00
Mathieu Lacage 4774f44062 fix small typo in debug log output 2007-11-21 10:02:17 +01:00
Mathieu Lacage f198acda79 use packet sockets for AP scenario too. 2007-11-21 09:54:43 +01:00
Mathieu Lacage 86a564094c use packet sockets and generate all graphics 2007-11-21 09:44:17 +01:00
Mathieu Lacage f2c5dd8d71 add constructors to specify the address of a device 2007-11-21 09:43:57 +01:00
Mathieu Lacage ed8ef96a61 add some info logs, improve snr vs ber curve output, linearize the ber calculations. 2007-11-20 16:45:52 +01:00
Mathieu Lacage 87a1ae56d7 plot the goodput for each data rate separately 2007-11-20 13:10:30 +01:00
Mathieu Lacage 63331e705a replace a buggy assert with a check with warning. 2007-11-20 12:48:51 +01:00
Mathieu Lacage 6f447c2b6a merge with HEAD 2007-11-19 16:54:04 +01:00
Mathieu Lacage f415e99a36 replace Dcf with DcfManager 2007-11-19 16:53:05 +01:00
Mathieu Lacage b699ad9ae1 use a simple request/grant scheme for dcf accesses 2007-11-19 16:20:30 +01:00
Mathieu Lacage 632a762654 The AIFSN has been taken into account in GetBackoffStartFor 2007-11-19 14:32:14 +01:00
Mathieu Lacage a4a3bc72fc test a backoff with an AIFSN != 1 2007-11-19 14:31:24 +01:00
Mathieu Lacage b809739d8c avoid decrementing by too many backoff slots 2007-11-19 14:22:45 +01:00
Mathieu Lacage 7ad2a4c3f2 another DCF test 2007-11-19 14:20:19 +01:00
Mathieu Lacage 4c4332c88b debugging output is more verbose. 2007-11-19 12:58:36 +01:00
Mathieu Lacage 6c0ef59a30 add WifiPhy::GetLastRxStart 2007-11-19 09:22:17 +01:00
Mathieu Lacage 83714d4d03 make the GetCw method public to allow DcaTxop to pick a random backoff duration 2007-11-19 08:38:48 +01:00
Mathieu Lacage 7498ef647c merge with HEAD 2007-11-17 18:58:47 +01:00
Mathieu Lacage 321dfcf741 add XXX for two bugs 2007-11-17 18:57:33 +01:00
Mathieu Lacage bdc6fcf5dd another more complex NAV test 2007-11-16 08:58:55 +01:00
Mathieu Lacage 50cd61e7c3 more comment on the test 2007-11-16 08:56:03 +01:00
Mathieu Lacage 125796fec7 simple NAV test 2007-11-16 08:54:16 +01:00
Mathieu Lacage d1d0e1c732 merge with HEAD 2007-11-16 08:48:57 +01:00
Mathieu Lacage 820fd1c13a merge with HEAD 2007-11-16 08:47:17 +01:00
Craig Dowell 577373aed9 Added tag release ns-3.0.8 for changeset 560a5091e0e6 2007-11-15 19:52:53 -08:00
Mathieu Lacage f992fe0b8d test internal collisions. 2007-11-15 16:34:53 +01:00
Mathieu Lacage ac99f9e46c we need to accumulate a record of all changes before applying them in one go. 2007-11-15 16:34:41 +01:00
Mathieu Lacage 225df7593f backoff end time is never in the past. 2007-11-15 16:23:26 +01:00
Mathieu Lacage 5ecad32251 if the backoff end is now, the backoff is expired. 2007-11-15 14:50:27 +01:00
Mathieu Lacage cfd44fc50c even if an access timer is running, we need to start a backoff if needed 2007-11-15 14:42:16 +01:00
Mathieu Lacage 20f47863bf ignore cwmin/cwmax parameters since we set the backoff slots for every collision. 2007-11-15 14:29:06 +01:00
Mathieu Lacage c6cfbd4e8c test interupted eifs 2007-11-15 14:26:40 +01:00
Mathieu Lacage 8422056873 more working tests. 2007-11-15 14:23:01 +01:00
Mathieu Lacage 80ba651375 add a small comment 2007-11-15 14:22:54 +01:00
Mathieu Lacage 18e5bf9c07 keep track of the last time a backoff was updated. 2007-11-15 14:21:48 +01:00
Mathieu Lacage 0394180213 a new test-case with some comments 2007-11-15 13:44:58 +01:00
Mathieu Lacage b52be989ed start a backoff only if no backoff is started 2007-11-15 13:37:51 +01:00
Mathieu Lacage b15597dbe7 forgot sifs + aifsn for test 2007-11-15 13:37:38 +01:00
Mathieu Lacage 6aa4ae880a add a new test-case 2007-11-15 13:24:09 +01:00
Mathieu Lacage 01d2d77a76 backoff is finished when the end of backoff is _equal_ to now. 2007-11-15 13:03:09 +01:00
Gustavo J. A. M. Carneiro 640a49e1ce Bug 105: Queue getter methods should be const 2007-11-15 11:41:42 +00:00
Mathieu Lacage c8cf6df4cd allow OnOffApplication to send more than 0xffffffff bytes 2007-11-21 09:08:32 +01:00
Gustavo J. A. M. Carneiro 7f0a1a1caf WAF: add a new --enable-modules configure option, to tell WAF to build only the specified set of ns-3 modules and its dependencies; programs depending on those modules are automatically excluded from the build. 2007-11-20 18:27:43 +00:00
Mathieu Lacage d9942c0c32 merge with HEAD 2007-11-15 11:22:41 +01:00
Mathieu Lacage 391adea516 update ignore list 2007-11-15 10:37:38 +01:00
Mathieu Lacage aad088e588 print-trace-sources.cc -> print-introspected-doxygen.cc 2007-11-15 10:35:55 +01:00
Mathieu Lacage ed31e39491 use the \valueref macro 2007-11-15 10:25:35 +01:00
Mathieu Lacage 34345b47d0 print default value list in trace source list doxygen output. 2007-11-15 10:24:51 +01:00
Mathieu Lacage 873a2c8dda add a valueref macro 2007-11-15 10:23:54 +01:00
Mathieu Lacage 838bef63b3 merge with Position -> Vector rename 2007-11-15 10:22:35 +01:00
Mathieu Lacage 6d97118181 merge with HEAD 2007-11-15 10:18:17 +01:00
Mathieu Lacage 008e02b03c add a new test 2007-11-15 09:44:23 +01:00
Mathieu Lacage 21baa41ccf timestep is a signed quantity. 2007-11-14 14:16:42 +01:00
Mathieu Lacage d20ccf186e handle NAV correctly 2007-11-14 14:11:11 +01:00
Mathieu Lacage 3128aadfe0 remove buggy test asserts 2007-11-14 14:03:38 +01:00
Mathieu Lacage 03da97b0b8 do not use GetBackoffSlots directly anymore 2007-11-14 14:02:03 +01:00
Mathieu Lacage 2d39b3c2d0 remove buggy assert and comment 2007-11-14 13:53:32 +01:00
Mathieu Lacage dada8dc1db improve debugging output. introduce GetBackoffStartFor and GetBackoffEndFor 2007-11-14 13:50:19 +01:00
Mathieu Lacage 5b47785ae4 add a ns3::MaxSeconds function 2007-11-14 13:45:17 +01:00
Mathieu Lacage c18e92df67 get rid of MacParameters from DcfManager 2007-11-14 12:43:01 +01:00
Mathieu Lacage 8828ac5d30 more debugging. 2007-11-14 12:36:08 +01:00
Mathieu Lacage 83d717bcae add debugging output 2007-11-14 12:23:56 +01:00
Mathieu Lacage 21f9524b3e a few more test asserts 2007-11-13 18:02:46 +01:00
Mathieu Lacage c7078a3e10 simplify memory management 2007-11-13 17:58:34 +01:00
Mathieu Lacage 1bbd9675b6 initialize more state variables 2007-11-13 17:58:22 +01:00
Mathieu Lacage 87db306da0 initialize state variables 2007-11-13 17:44:02 +01:00
Unknown c41da878f9 setup a simple test scenario 2007-11-13 17:40:39 +01:00
Unknown 0a17e5ab7f dcf test framework 2007-11-13 17:26:36 +01:00
Unknown 2f356fd916 add missing method implementations 2007-11-13 17:26:24 +01:00
Unknown 1bf52bda9e a new (wholy untested) Dcf implementation 2007-11-13 16:32:39 +01:00
Mathieu Lacage 89117a326c do nothing on cancel and explain why. 2007-11-09 13:25:01 +01:00
Mathieu Lacage 51bc877b4e update the last sequence control only for non-broadcast frames. 2007-11-09 13:24:38 +01:00
Mathieu Lacage f5772f0423 set the retry bit and use it to filter duplicates 2007-11-09 09:35:13 +01:00
Mathieu Lacage 95596a53b0 handle cancel events 2007-11-09 08:44:03 +01:00
Craig Dowell bb9c35ffea baranch merge 2007-11-08 17:05:37 -08:00
Mathieu Lacage 9e215a3493 calculate the delay, not -delay. 2007-11-08 15:25:57 +01:00
Mathieu Lacage 3321873fc6 implement AP beaconing 2007-11-08 15:23:06 +01:00
Mathieu Lacage fc57cac746 make sure that m_listener is not reset to zero _after_ calling a user-provided callback. This allows the user-provided callback to set the m_listener member to a new value if it wants to start a new transmission 2007-11-08 15:22:22 +01:00
Mathieu Lacage dbdd00fef8 zeroify the members after deleting them to improve debugging. 2007-11-08 13:58:26 +01:00
Mathieu Lacage 0986cb46d9 make debug build work 2007-11-08 13:57:50 +01:00
Mathieu Lacage e55384067b add WifiMacHeader::SetBeacon 2007-11-08 13:57:30 +01:00
Mathieu Lacage 1a8421bbfe use the holland set of modes. 2007-11-06 16:16:18 +01:00
Mathieu Lacage ecc4bab8f2 add the holland 802.11a set of modes. 2007-11-06 16:16:06 +01:00
Mathieu Lacage b5a64f2fae a real test 2007-11-06 15:11:22 +01:00
Mathieu Lacage 7e11cfb891 use the new style support 2007-11-06 15:05:56 +01:00
Mathieu Lacage cdcfbd8ab2 add style support 2007-11-06 15:05:47 +01:00
Mathieu Lacage 9964005525 use the gnuplot machinery to output a set of plots 2007-11-06 14:50:20 +01:00
Mathieu Lacage 3dd8898aaf generate correct output. avoid infinite loop. 2007-11-06 14:48:49 +01:00
Mathieu Lacage d3acfdfa07 fix optimized builds 2007-11-06 14:48:31 +01:00
Mathieu Lacage cb0eeaeb32 generate gnuplot-compatible data script files 2007-11-06 13:30:40 +01:00
Mathieu Lacage b114ba4ec6 print the throughput vs distance curve 2007-11-06 12:32:58 +01:00
Mathieu Lacage 688683fdaf change the default tx and gain to be 1db again. 2007-11-06 12:32:42 +01:00
Mathieu Lacage f0740d8235 simplify the code a bit. Make sure we handle correctly the calculation of the reference rx power 2007-11-06 10:37:12 +01:00
Mathieu Lacage bf33ac89eb remove dead method 2007-11-06 10:36:07 +01:00
Mathieu Lacage d030b978ab use dB instead of dbm where appropriate 2007-11-05 18:55:49 +01:00
Mathieu Lacage 1acb811437 clarify the formulas 2007-11-05 18:55:14 +01:00
Mathieu Lacage 1bf7be4d2a make the default match yans for debugging purposes 2007-11-05 17:41:58 +01:00
Mathieu Lacage 44096d2f95 add throughput printer 2007-11-05 16:45:22 +01:00
Mathieu Lacage 136cb036b4 test the friis model 2007-11-05 16:33:54 +01:00
Mathieu Lacage a1bfcd1216 test propagation losses 2007-11-05 16:31:52 +01:00
Mathieu Lacage 277173ae0f calculate correctly rx power 2007-11-05 16:31:16 +01:00
Mathieu Lacage 28e6e63c5d handle min distance for friis model in a saner way 2007-11-05 15:53:24 +01:00
Mathieu Lacage a49623136a document log distance propagation loss model. 2007-11-05 15:41:02 +01:00
Mathieu Lacage 9041f3ed1f Document the friis propagation model. 2007-11-05 14:54:40 +01:00
Mathieu Lacage 745412ffb8 define a new dox module 2007-10-31 16:39:16 +01:00
Mathieu Lacage 680c125dde fix dox warnings 2007-10-31 16:27:37 +01:00
Mathieu Lacage d072cdd527 doxygen 2007-10-31 16:26:31 +01:00
Mathieu Lacage 570126f8ff use Time for the beacon interval. 2007-10-31 16:26:18 +01:00
Mathieu Lacage 5de828fa15 dox for WifiPhy 2007-10-31 13:17:45 +01:00
Mathieu Lacage 32f3411eca remove unused loggers 2007-10-31 12:29:28 +01:00
Mathieu Lacage 7509e66617 phy state logger 2007-10-31 12:27:20 +01:00
Mathieu Lacage 92d65a529f derive WifiPhy from Object and manage it with a Ptr<> 2007-10-31 12:05:25 +01:00
Mathieu Lacage 51590ad30f basic tracing support 2007-10-31 11:45:04 +01:00
Mathieu Lacage ecd20983e8 merge with tip 2007-10-30 10:31:20 +01:00
Craig Dowell 7dca6e0b04 olsr gets new packet 2007-10-29 13:40:25 -07:00
Craig Dowell 60b6fb3d39 merge in packet.bundle 2007-10-29 12:48:01 -07:00
Mathieu Lacage 9d1a3eff16 port to new Channel API. 2007-10-29 16:34:26 +01:00
Mathieu Lacage d58602289d merge with tip again 2007-10-29 15:04:47 +01:00
Mathieu Lacage 8845f347d3 merge with tip 2007-10-29 15:04:23 +01:00
Mathieu Lacage d6611f02ba rename print-trace-sources to print-introspected-doxygen 2007-10-29 15:01:36 +01:00
Mathieu Lacage 3ed9dc6a94 fix a few missing \valueref 2007-10-29 15:01:14 +01:00
Mathieu Lacage dbfc58c5ed move default value output to print-trace-sources utility 2007-10-29 14:55:16 +01:00
Mathieu Lacage aedad2ccb0 use valueref where needed. 2007-10-29 14:45:43 +01:00
Mathieu Lacage 1aa79965c7 make the default value names more coherent. 2007-10-29 14:40:25 +01:00
Mathieu Lacage 4bef99703a define valueref alias 2007-10-29 10:44:56 +01:00
Mathieu Lacage 1afa21922f update config file to latest doxygen 2007-10-29 10:44:46 +01:00
Mathieu Lacage ca7f175fb7 add missing copyright header 2007-10-26 22:11:48 +02:00
Mathieu Lacage 81f5e4c039 remove extraneous empty line 2007-10-26 22:10:52 +02:00
Mathieu Lacage cb1b1daacd change <table> to <ul> 2007-10-26 17:11:02 +02:00
Mathieu Lacage 6862cc0ce9 output a default value list 2007-10-26 17:05:39 +02:00
Mathieu Lacage 6ff8bda568 utility program to print the list of default values 2007-10-26 14:16:40 +02:00
Mathieu Lacage 8e78937160 add missing copyright headers 2007-10-26 14:14:20 +02:00
Mathieu Lacage d7bfb88be9 add missing headers 2007-10-26 14:03:22 +02:00
Mathieu Lacage 46654ba28a add missing headers 2007-10-26 14:02:19 +02:00
Mathieu Lacage 34889dfb6a doxygen PropagationDelayModel 2007-10-26 14:00:13 +02:00
Mathieu Lacage e2a3b89175 doxygen PropagationLossModel 2007-10-26 13:49:33 +02:00
Mathieu Lacage 6a51a05171 replace distance by a pair of mobility models 2007-10-26 13:31:17 +02:00
Mathieu Lacage 09bfa883ac start of work towards a wifi documentation 2007-10-26 13:14:29 +02:00
Mathieu Lacage 6f0268171d basic doxygen documentation for users 2007-10-26 13:14:14 +02:00
Mathieu Lacage 4e5203a3dd set the supported rates in assoc resp frames 2007-10-24 20:43:22 +02:00
Mathieu Lacage 58363c9dab do not add a basic mode more than once. 2007-10-24 20:42:11 +02:00
Mathieu Lacage 0e7024488d handle basic rate support 2007-10-24 20:41:49 +02:00
Mathieu Lacage 6310a6040b fix coding style 2007-10-24 20:00:30 +02:00
Mathieu Lacage ec31e714d6 add size to logging output 2007-10-24 16:43:09 +02:00
Mathieu Lacage a80d3bcf38 simplify logging output 2007-10-24 16:28:28 +02:00
Mathieu Lacage ad9b41e45e try to simplify duration calculations 2007-10-24 16:02:10 +02:00
Mathieu Lacage 9d643387fb initialize the m_length field. 2007-10-24 15:05:17 +02:00
Mathieu Lacage c570beefbd check the ssid length 2007-10-23 14:00:53 +02:00
Mathieu Lacage 6f97972582 enable packet metadata for debugging 2007-10-23 13:40:08 +02:00
Mathieu Lacage 736368f441 improve slightly the SupportedRates print output 2007-10-23 13:39:49 +02:00
Mathieu Lacage 7aede726ca add missing space separator 2007-10-23 13:38:03 +02:00
Mathieu Lacage 228150cd72 add printing support 2007-10-23 13:12:04 +02:00
Mathieu Lacage 9f4f9e7b2f add printing support 2007-10-23 13:11:41 +02:00
Mathieu Lacage 629de5c931 add logging support 2007-10-23 13:11:23 +02:00
Mathieu Lacage 30af256bb6 add printing support 2007-10-23 13:11:10 +02:00
Mathieu Lacage 7340c86c61 enable logging 2007-10-23 12:49:09 +02:00
Mathieu Lacage 0c5de08870 ap/sta sample 2007-10-19 12:10:01 +02:00
Mathieu Lacage 36a6d0c93c handle the BasicRateSet in the AP 2007-10-18 17:19:53 +02:00
Mathieu Lacage 2d66b73e34 dynamically update the list of supported rates based on the ap supported rates 2007-10-18 15:59:33 +02:00
Mathieu Lacage 18517c1fe5 implement Reset and AddBasicMode 2007-10-18 15:58:19 +02:00
Mathieu Lacage 69dfc4fe32 add support for set/get supported rates in assoc resp packets 2007-10-18 15:12:39 +02:00
Mathieu Lacage d7fe272673 make sure we record all needed supported modes 2007-10-18 14:38:09 +02:00
Mathieu Lacage 40add040f9 convert int to uint32_t 2007-10-18 14:32:42 +02:00
Mathieu Lacage 766d7138ac control the rate control algorithms with default values. 2007-10-18 14:27:43 +02:00
Mathieu Lacage dc3fb38cbb support BRAND_NEW station in adhoc code. initialize the supported rates. 2007-10-18 13:37:22 +02:00
Mathieu Lacage eb1e734628 add dispose methods in subclasses of WifiNetDevice 2007-10-18 12:20:41 +02:00
Mathieu Lacage ba95d49a67 get rid of the dcf 2007-10-18 12:20:24 +02:00
Mathieu Lacage a90aee32a0 clear the list of NetDevice 2007-10-18 12:20:17 +02:00
Mathieu Lacage 8a9502ce01 dispose everything from WifiNetDevice::DoDispose 2007-10-18 11:53:35 +02:00
Mathieu Lacage 8d46c4debc dispose the channel from WifiNetDevice 2007-10-18 11:50:35 +02:00
Mathieu Lacage fe2ab99c52 remove buggy asserts 2007-10-18 11:25:33 +02:00
Mathieu Lacage a5467f201c cts, rts, and ack sizes must take into account fcs padding 2007-10-18 11:22:19 +02:00
Mathieu Lacage 976c3bbe98 eifs calculation is wrong: match the spec. 2007-10-18 11:21:40 +02:00
Mathieu Lacage 551de62f42 make sure that ack and cts delay take into account the fcs padding. 2007-10-18 11:21:14 +02:00
Mathieu Lacage 434226dd01 add time to debug output 2007-10-17 17:49:56 +02:00
Mathieu Lacage e770997d09 do not call Unref directly anymore. 2007-10-17 17:01:51 +02:00
Mathieu Lacage 52d42bca30 fix valgrind warning: initialize RngStream correctly 2007-10-17 16:26:42 +02:00
Mathieu Lacage 3b5eba1c85 make sure we pass the Rts duration to the SendCtsAfterRts method. fix debugging output. 2007-10-17 16:20:30 +02:00
Mathieu Lacage 76af0aa6ed make sure that each new MacStation is correctly initialized 2007-10-17 16:19:51 +02:00
Mathieu Lacage 4a6e000a07 convert to and from dbms when needed 2007-10-17 15:52:11 +02:00
Mathieu Lacage cf2fbcb6e3 log channel behavior 2007-10-17 15:51:37 +02:00
Mathieu Lacage 11c2f8c991 tx and rx gain should have no impact by default 2007-10-17 15:51:20 +02:00
Mathieu Lacage 0d3182c278 use dbms consistently in the propagation loss models 2007-10-17 15:50:38 +02:00
Mathieu Lacage 1d2a21fa1f initialize uniqueUid field 2007-10-17 13:39:05 +02:00
Mathieu Lacage c6763e76ee index starts at zero 2007-10-17 13:38:44 +02:00
Mathieu Lacage 818c1ea9e9 specify real type 2007-10-17 13:38:33 +02:00
Mathieu Lacage 0b4d0fcf67 implement operator << and an assert 2007-10-17 12:01:08 +02:00
Mathieu Lacage 384c4b998e add asserts and some debug log 2007-10-17 12:00:43 +02:00
Mathieu Lacage 449bd78db7 convert TRACE to NS_LOG 2007-10-16 18:09:49 +02:00
Mathieu Lacage 5d2227d3a6 remove 'all rights reserved' 2007-10-16 17:22:13 +02:00
Mathieu Lacage 0058449576 remove uneeded trailing ';' 2007-10-16 17:20:09 +02:00
Mathieu Lacage 2059a57d96 goto the right location before serializing the wifi trailer 2007-10-16 17:18:29 +02:00
Mathieu Lacage 8bb9ab629f remove bogus assert 2007-10-16 17:15:30 +02:00
Mathieu Lacage 73c536fa04 replace cassert by ns3/assert.h 2007-10-16 15:57:45 +02:00
Mathieu Lacage 2d07bbdf2c configure correctly the ipv4 layer 2007-10-16 15:43:26 +02:00
Mathieu Lacage 83e7cf54f4 merge with HEAD 2007-10-16 14:44:36 +02:00
Mathieu Lacage 54725d30b1 fix position printing code 2007-10-16 14:43:40 +02:00
Mathieu Lacage e688cc520b convert tracing to log system 2007-10-16 14:43:08 +02:00
Mathieu Lacage ec5e79f86b fix valgrind warning 2007-10-16 14:29:23 +02:00
Mathieu Lacage 87d56eb866 use the new RandomStream class and fix a small bug in the testsuite 2007-10-16 13:32:48 +02:00
Mathieu Lacage 2922488eb9 add wrapper class around RngStream for testing. 2007-10-16 13:32:19 +02:00
Mathieu Lacage b8230bf5e6 fix bogus assert 2007-10-16 13:31:51 +02:00
Mathieu Lacage e66a3625b4 make sure to terminate vararg list correctly 2007-10-16 10:54:50 +02:00
Mathieu Lacage 0c760dc107 build and link 2007-10-15 16:47:53 +02:00
Mathieu Lacage ad7ea01ee8 add some tests 2007-10-15 16:17:15 +02:00
Mathieu Lacage 1026821e33 add StringDefaultValue 2007-10-15 12:58:53 +02:00
Mathieu Lacage 0296999ec8 remove dead code 2007-10-11 16:53:42 +02:00
Mathieu Lacage b2a44942a8 use the default propagation models 2007-10-11 16:51:59 +02:00
Mathieu Lacage 268e4d5ec9 support DefaultValue 2007-10-11 16:16:31 +02:00
Mathieu Lacage 4f562dbbfb add missing trailing 0/(void *)0 2007-10-11 16:16:14 +02:00
Mathieu Lacage e9127c0427 add default value support 2007-10-11 15:43:47 +02:00
Mathieu Lacage b2545f4d89 missing file 2007-10-11 13:27:39 +02:00
Mathieu Lacage 9c922e0c73 use new WifiNetDevice naming 2007-10-11 13:23:33 +02:00
Mathieu Lacage d6721ea8ef add WifiNetDevice to build 2007-10-11 13:20:55 +02:00
Mathieu Lacage c8503d149e merge with HEAD 2007-10-11 13:15:21 +02:00
Mathieu Lacage d7f63afae7 do not use the Watchdog class 2007-10-11 10:47:01 +02:00
Mathieu Lacage f79ee4b582 fix build 2007-10-10 16:04:25 +02:00
Mathieu Lacage 03fd848f18 merge watchdog fix 2007-10-10 16:03:45 +02:00
Mathieu Lacage 258a44de1a build STA code 2007-10-10 16:03:26 +02:00
Mathieu Lacage 20a04408a6 install watchdog.h 2007-10-10 15:59:34 +02:00
Mathieu Lacage 662356311a merge with head 2007-10-10 15:49:59 +02:00
Mathieu Lacage 806cba6352 test the watchdog 2007-10-10 15:32:17 +02:00
Mathieu Lacage fc0089c0f4 add missing call to Simulator::Destroy to cleanup after test 2007-10-10 15:32:04 +02:00
Mathieu Lacage 2c9b70a674 a Watchdog class 2007-10-10 15:04:46 +02:00
Mathieu Lacage 0bb0cb7b93 implement TimerImpl::Invoke 2007-10-10 14:28:37 +02:00
Mathieu Lacage 0e9a8e6c3d move traits definition down 2007-10-10 13:30:35 +02:00
Mathieu Lacage c7d39c7975 split timer implementation outside of Timer class 2007-10-10 13:18:15 +02:00
Mathieu Lacage 382c3d1787 add NQap to build 2007-10-10 11:23:28 +02:00
Mathieu Lacage 2ac8e7e496 add management frame implementations 2007-10-10 11:18:19 +02:00
Mathieu Lacage 230645ffa5 add serialization/deserialization support to Ssid/SupportedRates 2007-10-09 17:19:13 +02:00
Mathieu Lacage 3861eada88 add new code to build 2007-10-09 16:47:34 +02:00
Mathieu Lacage a1691fda9b add SupportedRates to build 2007-10-09 16:40:24 +02:00
Mathieu Lacage ec7d64d30d avoid calling un-implemented method 2007-10-09 16:15:38 +02:00
Mathieu Lacage 8cda08d41c fix coding style 2007-10-09 16:11:37 +02:00
Mathieu Lacage 05fe040f88 add MacHighAdhoc to build 2007-10-09 16:11:08 +02:00
Mathieu Lacage 756cc86a23 add Mac48Address::GetBroadcast 2007-10-09 16:09:37 +02:00
Mathieu Lacage 9e470dffc3 remove all rights reserved mention 2007-10-09 16:03:09 +02:00
Mathieu Lacage 6e2080f092 rework MacStations to handle correctly Supported vs Basic rate sets and add IdealMacStations to build 2007-10-09 16:02:21 +02:00
Mathieu Lacage 24a0b73ce3 add DcaTxop to build 2007-10-09 12:42:45 +02:00
Mathieu Lacage 473c0eecb1 add missing class prefix 2007-10-09 12:42:20 +02:00
Mathieu Lacage dec333d063 add MacRxMiddle to build 2007-10-09 12:30:51 +02:00
Mathieu Lacage 61d85c75d3 add operator < 2007-10-09 12:30:37 +02:00
Mathieu Lacage 8dab22328c add MacTxMiddle to build 2007-10-09 12:23:14 +02:00
Mathieu Lacage ac0991a7cc add WifiMacQueue to build 2007-10-09 12:20:43 +02:00
Mathieu Lacage bc276b2bc1 add Dcf to build 2007-10-09 12:17:02 +02:00
Mathieu Lacage 1e6415ce45 add MacLow to build 2007-10-09 11:36:13 +02:00
Mathieu Lacage e4f6408939 do not include dead header 2007-10-09 11:07:18 +02:00
Mathieu Lacage 497bb74d5a replace header mode with preamble mode 2007-10-09 11:07:05 +02:00
Mathieu Lacage dee939e78c remove extra WifiPhy::SendPacket argument. Add header mode support 2007-10-09 10:21:46 +02:00
Mathieu Lacage bb9a9fb06d port to new MacStation API 2007-10-08 17:04:34 +02:00
Mathieu Lacage 1a0edab86e port ArfMacStations to new MacStation API 2007-10-08 17:02:20 +02:00
Mathieu Lacage 673ac3faa9 remove 'All rights reserved' 2007-10-08 16:04:59 +02:00
Mathieu Lacage 3833b9b585 remove 'All rights reserved' 2007-10-08 16:04:57 +02:00
Mathieu Lacage 6ba9224f32 port to new MacStation API 2007-10-08 16:04:12 +02:00
Mathieu Lacage d138a49895 implement broadcast/multicast MacStation 2007-10-08 15:58:07 +02:00
Mathieu Lacage 0e434f0212 fix copyright statement 2007-10-08 15:44:08 +02:00
Mathieu Lacage f807067337 use WifiMode rather than mode indexes in MacStations API. 2007-10-08 15:43:19 +02:00
Mathieu Lacage 5e5800363e add operator == for WifiMode 2007-10-08 15:42:07 +02:00
Mathieu Lacage d643cf8c1d add WifiMode mandatory flag 2007-10-08 15:36:37 +02:00
Mathieu Lacage 0873562023 add MacStations::LookupNonUnicast 2007-10-08 14:43:53 +02:00
Mathieu Lacage ca890b509a add Mac48Address::IsBroadcast/IsMulticast 2007-10-08 14:43:29 +02:00
Mathieu Lacage 59fc14c57c move mac-station code in mac-stations 2007-10-08 14:33:29 +02:00
Mathieu Lacage 728d858f15 add CrMacStations to build 2007-10-03 15:46:28 +02:00
Mathieu Lacage 2029981f00 build MacParameters 2007-10-03 15:44:02 +02:00
Mathieu Lacage 17a02b8fbb install header 2007-10-03 14:22:41 +02:00
Mathieu Lacage 75a174bc7b no need for ns3 prefix 2007-10-03 14:22:03 +02:00
Mathieu Lacage 086e01fcb8 no need for ns3 prefix 2007-10-03 14:21:19 +02:00
Mathieu Lacage a219428887 add missing header 2007-10-03 14:20:07 +02:00
Mathieu Lacage ca86b0acf9 add missing header 2007-10-03 14:19:54 +02:00
Mathieu Lacage f20df8a492 build WifiMacTrailer 2007-10-03 14:19:24 +02:00
Mathieu Lacage d742b306d7 forgot to add wscript file 2007-10-03 14:11:10 +02:00
Mathieu Lacage 119c647097 build WifiMacHeader 2007-10-03 14:08:31 +02:00
Mathieu Lacage 64c6fa6525 add more files to build 2007-10-03 13:12:26 +02:00
Mathieu Lacage 5a7965468d add MacStation to build 2007-10-03 13:11:28 +02:00
Mathieu Lacage 855ccbf300 add MacStations to build 2007-10-03 13:10:44 +02:00
Mathieu Lacage 9e055bd52f implement WifiPhy::GetChunkSuccessRate 2007-10-03 11:35:07 +02:00
Mathieu Lacage d4a36c2e0f use WifiMode rather than TransmissionMode 2007-10-03 11:01:17 +02:00
Mathieu Lacage 1d0c9511a5 Phy80211 -> WifiPhy 2007-10-02 12:42:16 +02:00
Mathieu Lacage cd73b37673 WifiPhy class 2007-10-02 12:41:04 +02:00
Mathieu Lacage caf0a2c143 add ssid to build 2007-10-02 11:38:47 +02:00
Mathieu Lacage 06cb649b55 add missing implementations 2007-10-02 11:36:12 +02:00
Mathieu Lacage 3745686f38 merge with trunk 2007-10-01 15:41:19 +02:00
Mathieu Lacage 327e60b275 do not use Packet objects directly. Use Ptr<Packet> instead 2007-10-01 14:15:56 +02:00
Mathieu Lacage 2450bac944 add Packet::Ref/Unref methods 2007-10-01 14:14:31 +02:00
Mathieu Lacage 46fe0fbc29 Simplify and optimize Create template function. Add Ptr::operator * 2007-10-01 14:07:53 +02:00
Mathieu Lacage 4bf8491d01 get a few more files to compile 2007-08-24 16:27:59 +02:00
Mathieu Lacage a62ac4df3a build wifi sample code 2007-08-24 15:19:20 +02:00
Mathieu Lacage 9a7206b971 merge 2007-08-24 15:12:23 +02:00
Mathieu Lacage e23f26a8f3 start of work towards port of wifi code 2007-08-24 15:12:12 +02:00
344 changed files with 32945 additions and 5529 deletions
+1 -1
View File
@@ -8,4 +8,4 @@
^doc/latex
^\.lock-wscript
^\.waf
^doc/trace-source-list\.h$
^doc/introspected-doxygen\.h$
+3
View File
@@ -7,3 +7,6 @@
267e2ebc28e4e4ae2f579e1cfc29902acade0c34 buffer-working-before-breaking
606df29888e7573b825fc891a002f0757166b616 release ns-3.0.6
36472385a1cc7c44d34fb7a5951b930010f4e8d2 release ns-3.0.7
560a5091e0e6ded47d269e2f2dee780f13950a63 release ns-3.0.8
4db981a0d9eb135e3e1c07765cff8d66f7a55cca release ns-3.0.9
b5bf2588cde2f1273b1095cc5c83a0c272e55370 release ns-3.0.10
+1
View File
@@ -2,6 +2,7 @@ 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)
Joe Kopena (tjkopena@cs.drexel.edu)
Mathieu Lacage (mathieu.lacage@sophia.inria.fr)
Emmanuelle Laprise (emmmanuelle.laprise@bluekazoo.ca)
George F. Riley (riley@ece.gatech.edu)
+30
View File
@@ -3,6 +3,36 @@
This file contains ns-3 release notes (most recent releases first).
Release 3.0.11 (2008/02/15)
========================
- Initial port of GTNetS TCP implementation (initial version
that does not support multitasking or delayed acknowledgments yet,
but supports a reliable stream service)
- Changes to the ns-3 object model to create a TypeId-based
metadata system
- lots of bug fixes throughout the system
- tutorial updates
Release 3.0.10 (2008/01/15)
========================
- Add tutorial document content;
- Valgrind option for "waf" tool;
- Doxygen organization changes.
Release 3.0.9 (2007/12/15)
========================
- A 802.11 model ported from Yans. This model supports:
* a rather extensive PHY model
* log-distance and friis propagation model
* a simple set of rate control algorithms (ARF, Ideal,
AARF, constant-rate)
* adhoc and infrastructure mode (beacon+assoc)
- Use smart pointer for Packet in the APIs
- A new contrib directory with helper classes:
EventGarbageCollector, Gnuplot
- Tracing support for Applications
- many bugs fixed
Release 3.0.8 (2007/11/15)
========================
- A simple error model
+1 -1
View File
@@ -1 +1 @@
3.0.8
3.0.11
+7 -5
View File
@@ -185,7 +185,7 @@ TAB_SIZE = 4
# will result in a user-defined paragraph with heading "Side Effects:".
# You can put \n's in the value part of an alias to insert newlines.
ALIASES =
ALIASES = valueref{1}="\ref DefaultValue\1 \"\1\""
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
# sources only. Doxygen will then generate output that is more tailored for C.
@@ -493,10 +493,12 @@ WARN_LOGFILE =
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
INPUT = src \
doc/main.txt \
doc/trace-source-list.h \
doc/tracing.h
INPUT = doc/modules \
doc/main.h \
doc/introspected-doxygen.h \
doc/tracing.h \
doc/howtos/ \
src
# This tag can be used to specify the character encoding of the source files that
# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default
+38
View File
@@ -0,0 +1,38 @@
/*!
\page callbacks Using ns-3 callbacks
\anchor howtos-callbacks
\section null_callbacks Null Callbacks
<b>Question:</b> The API I am using calls for using a callback (in the
function signature), but I do not
want to provide one. Is there a way to provide a null callback?
<b>Answer:</b> Use the ns3::MakeNullCallback construct:
\code
template<typename R>
Callback< R, T1, T2, T3, T4, T5, T6 > ns3::MakeNullCallback (void)
\endcode
Example usage: The ns3::Socket class uses callbacks to indicate completion
of events such as a successful TCP connect(). These callbacks are set
in the following function:
\code
void Socket::SetConnectCallback (Callback<void, Ptr<Socket> > connectionSucceeded,
Callback<void, Ptr<Socket> > connectionFailed,
Callback<void, Ptr<Socket> > halfClose);
\endcode
But suppose you do not care about registering a callback for the
halfClose event (but you want to register one for the
connectionSucceeded and connectionFailed cases). In that case, you
can pass a null callback as the third argument. You just need to
pass a callback with the matching signature, as follows:
\code
localSocket->SetConnectCallback (
MakeCallback (&ConnectionSucceededCallback),
MakeCallback (&ConnectionFailedCallback),
MakeNullCallback<void, Ptr<Socket> > () );
\endcode
*/
+17
View File
@@ -0,0 +1,17 @@
/*!
\page howtos ns-3 HOWTOs
\anchor howtos-anchor
This is an organized set of frequently asked questions (FAQ) and HOWTOs
for ns-3. This complements the following wiki pages:
- <a href="http://www.nsnam.org/wiki/index.php/User_FAQ">User FAQ</a>
- <a href="http://www.nsnam.org/wiki/index.php/Developer_FAQ">Developer FAQ</a>
Please consider contributing tips to either the wiki (yourself) or
by submitting a patch to this maintained documentation.
- \subpage callbacks
*/
+61
View File
@@ -0,0 +1,61 @@
/**
* \mainpage ns-3 Documentation
*
* \section intro-sec Introduction
* <a href="http://www.nsnam.org/">ns-3</a> documentation is maintained using
* <a href="http://www.doxygen.org">Doxygen</a>.
* Doxygen is typically used for
* API documentation, and organizes such documentation across different
* modules. This project uses Doxygen both for building the manual around
* the API documentation, and a separate GNU texinfo document is used for
* the manual.
*
* The ns-3 project documentation is organized as follows:
* - <b><a href="modules.html">modules</a></b>: The "Modules" tab (above)
* organizes all of the public API and supporting manual text
* along the source code directory structure. This forms the
* "ns-3 manual", and it is available in HTML and PDF forms.
* - \ref howtos-anchor "HOWTOs": A set of HOWTOs and FAQs is
* maintained on another Doxygen "Related Page"
* - <a href="http://www.nsnam.org/docs/tutorial/tutorial.html">tutorial</a>: The ns-3 tutorial is a separate document maintained in <a href="http://www.gnu.org/software/texinfo/"> GNU Texinfo</a>.
* - The <b><a href="http://www.nsnam.org/wiki/index.php/Main_Page">ns-3 wiki</a></b>
* contains additional user-contributed material. Some wiki-contributed
* material may migrate to and overlap with the Doxygen information.
*
* \section install-sec Building the Documentation
*
* ns-3 requires Doxygen version 1.5.4 or greater to fully build all items,
* although earlier versions of Doxygen will mostly work.
*
* Type "./waf check" followed by "./waf --doxygen" to build the documentation.
* There is a program that runs during "./waf check" that builds pieces of
* the documentation through introspection. The doc/ directory contains
* configuration for Doxygen (doxygen.conf and main.txt). The Doxygen
* build process puts html files into the doc/html/ directory, and latex
* filex into the doc/latex/ directory.
*
* \section module-sec Module overview
*
* 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
*
* More detail can be found in the <b><a href="modules.html">Modules</a></b>
* tab.
*
*/
/**
* \namespace ns3
* \brief Every class exported by the ns3 library is enclosed in the
* ns3 namespace.
*/
-68
View File
@@ -1,68 +0,0 @@
/**
* \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 logging, \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 set of low-level trace facilities integrated in the ns3::Object system: \ref tracing
* - 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 "core" 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.
*
* 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
*/
+67
View File
@@ -0,0 +1,67 @@
/**
* @anchor modules_anchor
*
* @defgroup simulator Simulator
* 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
*
* @defgroup core Core
* \brief 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 logging, \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 set of low-level trace facilities integrated in the ns3::Object system: \ref tracing
* - 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
*
* @defgroup common Common
* The "core" 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.
*
* @defgroup node Node
* 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
*
*
* @defgroup devices Devices
* The "devices" module contains:
* - a PointToPoint MAC device: ns3::PointToPointNetDevice, ns3::PointToPointChannel,
* and ns3::PointToPointTopology.
*
* @defgroup internetNode InternetNode
*
* 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.
*
* @defgroup applications Applications
*
* @defgroup mobility Mobility
*
* @defgroup routing Routing
*
* @defgroup constants Constants
* @brief Constants you can change
*
* @defgroup contrib Contrib
*/
+13 -12
View File
@@ -7,28 +7,29 @@ Steps in doing an ns-3 release
- update and check in VERSION to the latest release number
- confirm that Doxygen builds cleanly and without warnings
(./waf --doxygen), and check in any necessary changes
2. make a new "architecture.pdf" document and place it in the doc/ directory
of the ns-3-dev working directory
3. ./waf configure; ./waf dist
2. ./waf configure; ./waf dist
- this will create a ns-3.0.x.tar.bz2 tarball
4. test tarball on release platforms (waf check and maybe some other scripts)
5. once you are happy with the tarball, tag ns-3-dev with "release ns-3.0.X"
3. test tarball on release platforms (waf check and maybe some other scripts)
4. once you are happy with the tarball, tag ns-3-dev with "release ns-3.0.X"
- hg tag "release ns-3.0.x"
- hg push
6. clone the tagged ns-3-dev and place it on the repository
5. clone the tagged ns-3-dev and place it on the repository
- ssh code.nsnam.org; sudo; su code;
- cp -r /home/code/repos/ns-3-dev /home/code/repos/ns-3.0.x
- cd /home/code/repos/ns-3.0.x/.hg and edit the hgrc appropriately
7. upload "ns-3.0.x.tar.bz2" to the /var/www/html/releases/ directory on
- cd /home/code/repos/ns-3.0.x/.hg and edit the hgrc appropriately:
"description = ns-3.0.x release
name = ns-3.0.x"
6. upload "ns-3.0.x.tar.bz2" to the /var/www/html/releases/ directory on
the www.nsnam.org server
8. update web page
- give it 600 permissions, and user/group = apache
8. update web pages on www.nsnam.org (source is in the www/ module)
- add link to news.html
- update getting_started.html
- update documents.html
- update roadmap on wiki
- build and update Doxygen directory on the server
-- ssh www.nsnam.org; sudo tcsh; su nsnam;
-- ~/bin/update-doxygen-release
- update and upload software architecture document (PDF, HTML)
-- note: HTML image generation is not currently automatic
-- edit ~/bin/update-doxygen-release file and change RELEASE variable
to the right version number
-- run ~/bin/update-doxygen-release
9. announce to ns-developers, with summary of release notes
+38 -36
View File
@@ -1,8 +1,10 @@
/**
* \ingroup core
* \defgroup TraceSourceList List of trace sources
*/
/**
* \ingroup core
* \defgroup tracing Tracing
*
* The flexibility of the ns-3 tracing system comes at the cost of quite
@@ -55,7 +57,7 @@
* class MyModel
* {
* public:
* void DoSomething (Packet packet)
* void DoSomething (Ptr<Packet> packet)
* {
* // report this event on packet
* m_doSomething (packet);
@@ -63,7 +65,7 @@
* }
* private:
* // report every "something" function call.
* CallbackTraceSource<Packet> m_doSomething;
* CallbackTraceSource<Ptr<Packet> > m_doSomething;
* };
* \endcode
* Every type of trace source derives from the ns3::TraceSource base class.
@@ -86,10 +88,10 @@
* std::cout << "cwnd=" << newValue << std::endl;
* }
* void
* DoSomethingTraceSink (const TraceContext &context, Packet packet)
* DoSomethingTraceSink (const TraceContext &context, Ptr<Packet> packet)
* {
* // for example, print the arguments
* std::cout << "packet " << packet << std::endl;
* // for example, print the packet
* std::cout << "packet " << packet->Print () << std::endl;
* }
* \endcode
* Each of these sink function takes, as a first argument, a reference to a
@@ -121,19 +123,19 @@
* class MyModel
* {
* public:
* void DoSomething (Packet packet)
* void DoSomething (Ptr<Packet> packet)
* {
* // report this event on packet
* m_doSomething (packet);
* // do something
* }
* CallbackTraceSource<Packet> *PeekSomethingTraceSource (void) const
* CallbackTraceSource<Ptr<Packet>> *PeekSomethingTraceSource (void) const
* {
* return &m_doSomething
* }
* private:
* // report every "something" function call.
* CallbackTraceSource<Packet> m_doSomething;
* CallbackTraceSource<Ptr<Packet>> m_doSomething;
* };
* \endcode
* If your users hold a pointer to an instance of MyModel, and if they want to connect
@@ -142,12 +144,12 @@
* sink with the MakeCallback function.
* \code
* void
* MySomethingSink (const TraceContext &context, Packet packet)
* MySomethingSink (const TraceContext &context, Ptr<Packet> packet)
* {
* // do whatever you want.
* }
* MyModel *model = ...;
* CallbackTraceSource<Packet> *source = model->PeekSomethingTraceSource ();
* CallbackTraceSource<Ptr<Packet>> *source = model->PeekSomethingTraceSource ();
* source->AddCallback (MakeCallback (&MySomethingSink));
* \endcode
*
@@ -170,13 +172,13 @@
* located in some nodes of the system, we could write the following:
* \code
* void
* DoSomethingTraceSink (const TraceContext &context, Packet packet)
* DoSomethingTraceSink (const TraceContext &context, Ptr<Packet> packet)
* {
* // for example, print the arguments
* std::cout << "packet: " << packet << std::endl;
* // for example, print the packet
* std::cout << "packet: " << packet->Print () << std::endl;
* }
* // connect the above sink to a matching trace source
* NodeList::Connect ("/nodes/* /devices/* /rx", MakeCallback &DoSomethingTraceSink);
* NodeList::Connect ("/nodes/* /devices/* /rx", MakeCallback (&DoSomethingTraceSink));
* \endcode
*
* The connection path string "/nodes/* /devices/* /rx" matches the "rx" trace source
@@ -203,10 +205,10 @@
* the TraceContext object:
* \code
* void
* DoSomethingTraceSink (const TraceContext &context, Packet packet)
* DoSomethingTraceSink (const TraceContext &context, Ptr<Packet> packet)
* {
* // for example, print the arguments
* std::cout << "context=\"" << context << "\" packet: " << packet << std::endl;
* // for example, print the packet
* std::cout << "context=\"" << context << "\" packet: " << packet->Print () << std::endl;
* }
* \endcode
* The above code is going to generate output which looks like the following:
@@ -223,7 +225,7 @@
* in the \ref TraceSourceList. For example, we could write the following to
* generate adhoc trace output:
* \code
* void DeviceRxSink (const TraceContext &context, const Packet &packet)
* void DeviceRxSink (const TraceContext &context, Ptr<const Packet> packet)
* {
* NodeListIndex nodeIndex;
* NodeNetDeviceIndex deviceIndex;
@@ -231,7 +233,7 @@
* context.GetElement (deviceIndex);
* std::cout << "node-index=" << nodeIndex.Get ();
* std::cout << ", device-index=" << deviceIndex.Get ();
* std::cout << ", packet: " << packet;
* std::cout << ", packet: " << packet->Print ();
* std::cout << std::endl;
* }
* \endcode
@@ -247,7 +249,7 @@
* class MyModel
* {
* public:
* void DoSomething (Packet packet)
* void DoSomething (Ptr<Packet> packet)
* {
* // report this event on packet with value
* m_doSomething (packet);
@@ -255,7 +257,7 @@
* }
* private:
* // report every "something" function call.
* CallbackTraceSource<Packet> m_doSomething;
* CallbackTraceSource<Ptr<Packet>> m_doSomething;
* };
* \endcode
*
@@ -279,7 +281,7 @@
* virtual Ptr<TraceResolver> GetTraceResolver (void) const;
* private:
* // the new trace source to export.
* CallbackTraceSource<Packet> m_rxSource;
* CallbackTraceSource<Ptr<Packet>> m_rxSource;
* };
* \endcode
*
@@ -362,15 +364,15 @@
* class MyModel
* {
* private:
* CallbackTraceSource<Packet> m_rxSource;
* CallbackTraceSource<Packet> m_txSource;
* CallbackTraceSource<Packet> m_dropSource;
* CallbackTraceSource<Ptr<Packet>> m_rxSource;
* CallbackTraceSource<Ptr<Packet>> m_txSource;
* CallbackTraceSource<Ptr<Packet>> m_dropSource;
* };
* \endcode
* When a single sink is connected to all 3 sources here, one might want
* to write code like the following:
* \code
* void DeviceRxSink (const TraceContext &context, const Packet &packet)
* void DeviceRxSink (const TraceContext &context, Ptr<const Packet> &packet)
* {
* switch (type) {
* case RX:
@@ -407,23 +409,23 @@
* };
* private:
* // generate events
* void NotifyRxPacket (Packet p) {
* void NotifyRxPacket (Ptr<Packet> p) {
* m_rxSource (p, MyModel::RX);
* }
* void NotifyTxPacket (Packet p) {
* void NotifyTxPacket (Ptr<Packet> p) {
* m_rxSource (p, MyModel::TX);
* }
* void NotifyDropPacket (Packet p) {
* void NotifyDropPacket (Ptr<Packet> p) {
* m_rxSource (p, MyModel::DROP);
* }
* CallbackTraceSource<Packet,enum TraceType> m_rxSource;
* CallbackTraceSource<Packet,enum TraceType> m_txSource;
* CallbackTraceSource<Packet,enum TraceType> m_dropSource;
* CallbackTraceSource<Ptr<Packet>,enum TraceType> m_rxSource;
* CallbackTraceSource<Ptr<Packet>,enum TraceType> m_txSource;
* CallbackTraceSource<Ptr<Packet>,enum TraceType> m_dropSource;
* };
* \endcode
* These 3 new sources can be connected easily to a new trace sink:
* \code
* void ASimpleTraceSink (const TraceContext &context, const Packet &packet, enum MyModel::TraceType type)
* void ASimpleTraceSink (const TraceContext &context, Ptr<const Packet> packet, enum MyModel::TraceType type)
* {
* // here, read the "type" argument
* }
@@ -447,7 +449,7 @@
* define a new MyModelTraceType class which contains the type of trace, your users can
* then write trace sink code which looks like this:
* \code
* void AFancyTraceSink (const TraceContext &context, const Packet &packet)
* void AFancyTraceSink (const TraceContext &context, Ptr<const Packet> packet)
* {
* MyModelTraceType type;
* if (context.GetElement (type))
@@ -471,9 +473,9 @@
* Of course, since the type of trace is stored in the TraceContext, your users can
* also take the shortcut which uses the printing functionality of the TraceContext:
* \code
* void ALessFancyTraceSink (const TraceContext &context, const Packet &packet)
* void ALessFancyTraceSink (const TraceContext &context, Ptr<const Packet> packet)
* {
* std::cout << "context=\"" << context << "\" packet: " << packet << std::endl;
* std::cout << "context=\"" << context << "\" packet: " << packet->Print () << std::endl;
* }
* \endcode
* which will generate something like the following when the trace source comes
+330
View File
@@ -0,0 +1,330 @@
@node ns-3 Callbacks
@chapter ns-3 Callbacks
Some new users to @command{ns-3} are unfamiliar with an extensively used
programming idiom used throughout the code: the ``ns-3 callback''. This
chapter provides some motivation on the callback, guidance on how to use
it, and details on its implementation.
@menu
* Motivation::
* Using the Callback API::
* Callback locations in ns-3::
* Implementation details::
@end menu
@node Motivation
@section Motivation
Consider that you have two simulation models A and B, and you wish
to have them pass information between them during the simulation. One
way that you can do that is that you can make A and B each explicitly
knowledgable about the other, so that they can invoke methods on each
other.
@verbatim
class A {
public:
void ReceiveInput ( // parameters );
...
}
(in another source file:)
class B {
public:
void ReceiveInput ( // parameters);
void DoSomething (void);
...
private:
A* a_instance; // pointer to an A
}
void
B::DoSomething()
{
// Tell a_instance that something happened
a_instance->ReceiveInput ( // parameters);
...
}
@end verbatim
This certainly works, but it has the drawback that it introduces a
dependency on A and B to know about the other at compile time (this
makes it harder to have independent compilation units in the simulator)
and is not generalized; if in a later usage scenario, B needs to talk
to a completely different C object, the source code for B needs to be
changed to add a ``c_instance'' and so forth. It is easy to see that
this is a brute force mechanism of communication that can lead to
programming cruft in the models.
This is not to say that objects should not know about one another
if there is a hard dependency between them, but that often the model
can be made more flexible if its interactions are less constrained at
compile time.
This is not an abstract problem for network simulation research,
but rather it has been a source of problems in previous simulators,
when researchers want to extend or modify the system to do different
things (as they are apt to do in research). Consider, for example,
a user who wants to add an IPsec security protocol sublayer
between TCP and IP:
@verbatim
------------ -----------
| TCP | | TCP |
------------ -----------
| becomes -> |
----------- -----------
| IP | | IPsec |
----------- -----------
|
-----------
| IP |
-----------
@end verbatim
If the simulator has
made assumptions, and hard coded into the code, that IP always talks
to a transport protocol above, the user may be forced to hack the
system to get the desired interconnections.
An alternative that provides this flexibility is to use a level of
indirection that is commonly known in programming as a callback.
A callback function is not invoked explicitly by the caller but is
rather delegated to another function that receives the callback
function's address and can call it.
You may be familiar with function pointers in C or C++; these can
be used to implement callbacks. For more information on introductory
callbacks, an online reference is:
@uref{http://www.inquiry.com/techtips/cpp_pro/10min/10min0300.asp,,Declaring Function Pointers and Implementing Callbacks} and
@uref{http://en.wikipedia.org/wiki/Callback_(computer_science),,Callback (computer science)-- Wikipedia}.
The callback API in @command{ns-3} is designed to minimize the overall
coupling between various pieces of of the simulator
by making each module depend on the callback API
itself rather than depend on other modules. It acts as a sort of
third-party to which work is delegated and which forwards this
work to the proper target module. This callback API, being based
on C++ templates,
is type-safe; that is, it performs static type checks to enforce
proper signature compatibility between callers and callees. It
is therefore more type-safe to use than traditional function
pointers, but the syntax may look imposing at first. This section
is designed to walk you through the callback system so that you
can be comfortable using it in @command{ns-3}.
@node Using the Callback API
@section Using the Callback API
The Callback API is fairly minimal, providing only two services:
@itemize @bullet
@item callback type declaration: a way to declare a type of callback
with a given signature, and,
@item callback instantiation: a way to instantiate a
template-generated forwarding callback which can forward any calls
to another C++ class member method or C++ function.
@end itemize
This is best observed via walking through an example, based on
@code{samples/main-callback.cc}.
@node Using the Callback API with static functions
@subsection Using the Callback API with static functions
Consider a function:
@verbatim
static double
CbOne (double a, double b)
{
std::cout << "invoke cbOne a=" << a << ", b=" << b << std::endl;
return a;
}
@end verbatim
Consider also the following main program snippett:
@verbatim
int main (int argc, char *argv[])
{
// return type: double
// first arg type: double
// second arg type: double
Callback<double, double, double> one;
}
@end verbatim
This class template Callback implements what is known as the Functor
Design Pattern. It is used to declare the type of a callback. It contains
one mandatory argument (the return type of the function to be assigned
to this callback) and up to five optional arguments, which each specify
the type of the arguments (if your function has more than five arguments,
then this can be handled by extending the callback implementation).
So in the above, we have a declared a callback named "one" that will
eventually hold a function pointer. The function that it will hold
must return double and must support two double arguments. If one
tries to pass a function whose signature does not match the declared
callback, the compilation will fail.
Now, we need to tie together this callback instance and the actual
target function (CbOne). Notice above that CbOne has the same function
signature types as the callback-- this is important. We can
pass in any such properly-typed function to this callback. Let's
look at this more closely:
@verbatim
static double CbOne (double a, double b) {}
^ ^ ^
| ---| ------|
| | |
Callback<double, double, double> one;
@end verbatim
You can only bind a function to a callback if they have the matching
signature. The first template argument is the return type, and the
additional template arguments are the types of the arguments of
the function signature.
Now, let's bind our callback "one" to the function that matches its
signature:
@verbatim
// build callback instance which points to cbOne function
one = MakeCallback (&CbOne);
@end verbatim
Then, later in the program, if the callback is to be used, it can be
used as follows:
@verbatim
// this is not a null callback
NS_ASSERT (!one.IsNull ());
// invoke cbOne function through callback instance
double retOne;
retOne = one (10.0, 20.0);
@end verbatim
The check @code{IsNull()} ensures that the callback is not null; that there
is a function to call behind this callback. Then, @code{one()} returns the
same result as if @code{CbOne()} had been called directly.
@node Using the Callback API with member functions
@subsection Using the Callback API with member functions
Generally, you will not be calling static functions but instead
public member functions of an object. In this case, an extra
argument is needed to the MakeCallback function, to tell the system
on which object the function should be invoked. Consider this example,
also from main-callback.cc:
@verbatim
class MyCb {
public:
int CbTwo (double a) {
std::cout << "invoke cbTwo a=" << a << std::endl;
return -5;
}
};
int main ()
{
...
// 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);
...
}
@end verbatim
Here, we pass a (raw) pointer to the @code{MakeCallback<>} function,
that says, when @code{two ()} is invoked, to call the @code{CbTwo} function
on the object pointed to by @code{&cb}.
A variation of this is used when objects are referred to by ns-3 smart
pointers. The MakeCallback API takes a raw pointer, so we need to
call @code{PeekPointer ()} to obtain this raw pointer. So the example
above would look like:
@verbatim
class MyCb : public Object {
public:
int CbTwo (double a) {
std::cout << "invoke cbTwo a=" << a << std::endl;
return -5;
}
};
int main ()
{
...
// return type: int
// first arg type: double
Callback<int, double> two;
Ptr<MyCb> cb = CreateObject<MyCb> ();
// build callback instance which points to MyCb::cbTwo
two = MakeCallback (&MyCb::CbTwo, PeekPointer (cb));
...
}
@end verbatim
@node Building Null Callbacks
@subsection Building Null Callbacks
It is possible for callbacks to be null; hence it may be wise to
check before using them. There is a special construct for a null
callback, which is preferable to simply passing "0" as an argument;
it is the @code{MakeNullCallback<>} construct:
@verbatim
two = MakeNullCallback<int, double> ();
// invoking a null callback is just like
// invoking a null function pointer:
// it will crash at runtime.
//int retTwoNull = two (20.0);
NS_ASSERT (two.IsNull ());
@end verbatim
@node Callback locations in ns-3
@section Callback locations in @command{ns-3}
Where are callbacks frequently used in @command{ns-3}? Here are some of the
more visible ones to typical users:
@subsection Socket API
@subsection Layer-2/Layer-3 API
@subsection Tracing subsystem
@subsection Routing
Route Reply
@node Implementation details
@section Implementation details
This section is advanced explanation for C++ experts interested in
the implementation, and may be skipped by most users.
This code was originally written based on the techniques described
@uref{http://www.codeproject.com/cpp/TTLFunction.asp,,here}.
It was subsequently rewritten to follow the architecture
outlined in
@uref{http://www.amazon.com/Modern-C\%2B\%2B-Design-Programming-Patterns/dp/0201704315/ref=pd_bbs_sr_1/102-0157303-1900156?ie=UTF8\&s=books\&qid=1187982662\&sr=1-1,,Modern C++ Design: Generic Programming and Design Patterns Applied-- Alexandrescu}, chapter 5, "Generalized Functors".
This code uses:
@itemize @bullet
@item default template parameters to saves users from having to
specify empty parameters when the number of parameters
is smaller than the maximum supported number
@item the pimpl idiom: the Callback class is passed around by
value and delegates the crux of the work to its pimpl pointer.
@item 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.
@item a reference list implementation to implement the Callback's
value semantics.
@end itemize
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.
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

File diff suppressed because it is too large Load Diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

File diff suppressed because it is too large Load Diff
+468
View File
@@ -0,0 +1,468 @@
@c ========================================================================
@c Simulation Output
@c ========================================================================
@node Simulation Output
@chapter Simulation Output
At this point, you should be able to execute any of the built-in
programs distributed with @command{ns-3}. Next, we will look at
how to generate and tailor the simulation output, before turning
to how to modify simulation scripts to do different things.
@node Tracing Basics
@section Tracing Basics
The whole point of simulation is to generate output for further
study, and the @command{ns-3} tracing system is a primary
mechanism for this.
Since @command{ns-3} is a C++ program, standard facilities for
generating output from C++ programs apply:
@verbatim
#include <iostream>
...
int main ()
{
...
std::cout << "The value of x is " << x << std::endl;
...
}
@end verbatim
The goal of the @command{ns-3} tracing system is to
provide a structured way to configure the simulator to output results
in standard or modifiable formats.
@itemize @bullet
@item For basic tasks, the tracing system should allow the user to
generate standard tracing for popular tracing sources, and to customize
which objects generate the tracing.
@item Intermediate users will be able to extend the tracing system to
modify the output format generated, or to insert new tracing sources,
without modifying the core of the simulator.
@item Advanced users can modify the simulator core to add new
tracing sources and sinks.
@end itemize
The @command{ns-3} tracing system is fundamentally built on the
concept of separating tracing sources from sinks.
@enumerate
@item Trace sources (e.g., provide access to every packet received)
@item Trace sinks (e.g., print out the packet)
@item A mechanism to tie together sources and sinks
@end enumerate
The rationale for this division is to allow users to attach new
types of sinks to existing tracing sources, without requiring
users to edit and recompile the core of the simulator.
Thus, in the example above, a user could write a new tracing sink
and attach it to an existing tracing source. What remains to
be defined is a way for users to find these hooks (tracing sources)
and attach sinks to them. A new tracing namespace is defined for
this purpose.
We will first walk through how some pre-defined sources and sinks
are provided and may be customized with little user effort. We
return later in this chapter to advanced tracing configuration including
extending the tracing namespace and creating new tracing sources.
@subsection ASCII tracing
@cindex ASCII
For Internet nodes, the ASCII trace wrapper is a wrapper around
the @command{ns-3} low-level
tracing system that lets you get access to underlying trace events easily.
The output of a trace of a simulation run is an ASCII file --- thus the name.
In the spririt of keeping things simple, you won't be able to control or
configure the output at this stage.
For those familiar with @command{ns-2} output, this type of trace is
analogous to the @command{out.tr} generated by many scripts.
@cindex tracing packets
Let's just jump right in. As usual, we need to include the definitions
related to using ASCII tracing (don't edit any files quite yet):
@verbatim
#include "ns3/ascii-trace.h"
@end verbatim
We then need to add the code to the script to actually enable the ASCII tracing
code. The following code must be inserted before the call to
@code{Simulator::Run ();}:
@verbatim
AsciiTrace asciitrace ("tutorial.tr");
asciitrace.TraceAllQueues ();
asciitrace.TraceAllNetDeviceRx ();
@end verbatim
The first line declares an object of type @code{AsciiTrace} named
@code{asciitrace} and passes a string parameter to its constructor. This
parameter is a file name to which all of the trace information will be written.
The second line, @code{asciitrace.TraceAllQueues ();} asks the trace object to
arrange that all queue operations (enqueue, dequeue, drop) on the queues
in all of the nodes of the system be traced. On the receive side,
@code{asciitrace.TraceAlllNetDeviceRx ()} traces packets received by
a NetDevice. For those familiar with @command{ns-2}, these are equivalent
to the popular trace points that log "+", "-", "d", and "r" events.
Try running the following program from the command line:
@verbatim
./waf --run tutorial-csma-echo-ascii-trace
@end verbatim
@cindex tutorial.tr
Just as you have seen previously, you will see some messages from @emph{Waf}
and then the ``Compilation finished successfully'' message. The
next message, @code{UDP Echo Simulation} is from the running program. When
it ran, the program will have created a file named @code{tutorial.tr}.
Because of the way that Waf works, the file is not created in the local
directory, it is created at the top-level directory of the repository. So,
change into the top level directory and take a look at the file
@code{tutorial.tr} in your favorite editor.
@subsubsection Parsing Ascii Traces
@cindex parsing ascii traces
This section parses in detail the structure of the ascii tracing
output. If you find this output format self explanatory (it
resembles tcpdump output), you may skip to the next
section on pcap tracing.
@cindex trace event
There's a lot of information there in a pretty dense form, but the first thing
to notice is that there are a number of distinct lines in this file. It may
be difficult to see this clearly unless you widen your windows considerably.
Each line in the file corresponds to a @emph{trace event}. A trace event
happens whenever specific conditions happen in the simulation. In this case
we are tracing events on the @emph{device queue} present in every net device
on every node in the simulation. The device queue is a queue through which
every packet destined for a channel must pass --- it is the device
@emph{transmit} queue. Note that each line in the trace file begins with a
lone character (has a space after it). This character will have the following
meaning:
@cindex enqueue
@cindex dequeue
@cindex drop
@itemize @bullet
@item @code{+}: An enqueue operation occurred on the device queue;
@item @code{-}: A dequeue operation occurred on the device queue;
@item @code{d}: A packet was dropped, typically because the queue was full.
@end itemize
Let's take a more detailed view of the first line. I'll break it down into
sections (indented for clarity) with a two digit reference number on the
left side:
@verbatim
00 +
01 2
02 nodeid=0
03 device=0
04 queue-enqueue
05 pkt-uid=9
06 ETHERNET
07 length/type=0x806,
08 source=08:00:2e:00:00:00,
09 destination=ff:ff:ff:ff:ff:ff
10 ARP(request
11 source mac: 08:00:2e:00:00:00
12 source ipv4: 10.1.1.1
13 dest ipv4: 10.1.1.2)
14 ETHERNET fcs=0
@end verbatim
@cindex trace event
@cindex simulation time
The first line of this expanded trace event (reference number 00) is the
queue operation. We have a @code{+} character, so this corresponds to an
@emph{enqueue} operation. The second line (reference 01) is the simulation
time expressed in seconds. You may recall that we asked the
@code{UdpEchoClient} to start sending packets at two seconds. Here we see
confirmation that this is, indeed, happening.
@cindex node number
@cindex net device number
@cindex smart pointer
The next lines of the example listing (references 02 and 03) tell us that
this trace event originated in a given node and net device. Each time a node
is created it is given an identifying number that monotonically increases from
zero. Therefore, @code{nodeid=0} means that the node in which the given trace
event originated is the first node we created. In the case of our script,
this first node is is the node pointed to by the smart pointer @code{n0}. Not
too surpsisingly, this is also the node to which we attached the
@code{UdpEchoClient}. The device number is local to each node, and so the
device given by @code{device=0} is the first net device that we added to the
node in question. In our simulation, this corresponds to the
@code{CsmaNetDevice} we added to node zero (@code{n0}).
@cindex uid
@cindex unique ID
@cindex packet
The next line (reference 04) is a more readable form of the operation code
seen in the first line --- i.e., the character @code{+} means
@code{queue-enqueue}. Reference number 05 indicates that the @emph{unique id}
of the packet being enqueued is @code{9}. The fact that the first packet we
see has a unique ID of 9 should indicates to you that other things have
happened in the protocol stack before we got to this point. This will become
clear momentarily.
@cindex Ethernet
@cindex MAC address
Reference items 06 and 14 indicate that this is an Ethernet packet with
a zero (not computed) checksum (note the indentation to make parsing this
trace event a little easier). Reference 08 and 09 are the source and
destination addresses of this packet. The packet is from the MAC address we
assigned to the node zero net device in the script, and is destined for the
broadcast address --- this is a broadcast packet.
@cindex Address Resolution Protocol
@cindex ARP
@cindex ARP|request
Reference items 10 through 13 make clear what is happening. This is an ARP
(Address Resolution Protocol) request for the MAC address of the node on
which the @code{UdpEchoServer} resides. The protocol stack can't send a UDP
packet to be echoed until it knows (resolves) the MAC address; and this trace
event corresponds to an ARP request being queued for transmission to the local
network. The next line in the trace file (partially expanded),
@verbatim
00 -
01 2
02 nodeid=0
03 device=0
04 queue-dequeue
05 pkt-uid=9
...
@end verbatim
shows the (same) ARP request packet being dequeued from the device queue by
the net device and (implicitly) being sent down the channel to the broadcast
MAC address. We are not tracing net device reception events so we don't
actually see all of the net devices receiving the broadcast packet. We do,
however see the following in the third line of the trace file:
@verbatim
00 +
01 2.00207
02 nodeid=1
03 device=0
04 queue-enqueue
05 pkt-uid=10
06 ETHERNET
07 length/type=0x806,
08 source=08:00:2e:00:00:01,
09 destination=08:00:2e:00:00:00,
10 ARP(reply
11 source mac: 08:00:2e:00:00:01
12 source ipv4: 10.1.1.2
13 dest mac: 08:00:2e:00:00:00
14 dest ipv4: 10.1.1.1)
15 ETHERNET fcs=0
@end verbatim
@cindex simulation time
@cindex ARP|response
Notice that this is a queue-enqueue operation (references 00 and 04) happening
on node one (reference 02) at simulation time 2.00207 seconds (reference 01).
Looking at the packet payload (references 10-14) we see that this is an ARP
reply to the request sent by node one. Note that the simulation time
(reference 01) is now 2.00207 seconds. This is direct result of the data rate
(5 mb/s) and latency (2 ms) parameters that we passed to the
@code{CsmaChannel} when we created it. Clearly the ARP request packet was
sent over the channel and received approximately 2 ms later by node one. A
corresponding ARP response packet was created and enqueued on node one's net
device. It is this enqueue trace event that has being logged.
@cindex queue
@cindex queue|transmit
@cindex echo
Given the current state of affairs, the next thing you may expect to see is
this ARP request being received by node zero, but remember we are only looking
at trace events on the device @emph{transmit} queue. The reception of the ARP
response by node zero will not directly trigger any trace event in this case,
but it will enable the protocol stack to continue what it was originally doing
(trying to send an echo packet). Thus, the next line we see in the trace file
(@code{tutorial.tr}) is the first UDP echo packet being sent to the net device.
@verbatim
00 +
01 2.00415
02 nodeid=0
03 device=0
04 queue-enqueue
05 pkt-uid=7
06 ETHERNET
07 length/type=0x800,
08 source=08:00:2e:00:00:00,
09 destination=08:00:2e:00:00:01
10 IPV4(
11 tos 0x0
12 ttl 64
13 id 0
14 offset 0
15 flags [none]
16 length: 1052) 10.1.1.1 > 10.1.1.2
17 UDP(length: 1032)
18 49153 > 7
19 DATA (length 1024)
20 ETHERNET fcs=0
@end verbatim
@cindex simulation time
@cindex echo
@cindex ARP
@cindex ARP|request
@cindex ARP|response
@cindex IP
@cindex Ipv4
I won't go into too much detail about this packet, but I will point out a
few key items in the trace. First, the packet was enqueued at simulation time
of 2.00415 seconds. This time reflects the fact that the echo client
application started at 2. seconds and there were two ARP packets transmitted
across the network (two milliseconds + data transmission time each way). The
packet unique identifier (reference 05) is 7. Notice that this is a lower
number than the ARP request packet, which had a unique ID of 9. This tells
us that the UDP packet was actually created before the ARP request packet ---
which makes perfect sense since it was the attempt to send packet 7 that
triggered sending the ARP request packet 9. Note that this an Ethernet
packet (reference 06) like all other packets in this simulation, however this
particular packet carries an IPV4 payload and therefore has an IP version 4
header (indicated by references 10-16). This Ipv4 in turn contains a UDP
header (references 17, 18) and finally 1024 bytes of data (reference 20).
Clearly, this is the UDP echo packet emitted by the
@code{UdpEchoClient Application}.
The next trace event is an ARP request from node one. We can infer that node
one has received the UDP echo packet and the @code{UdpEchoServer Application}
on that node has turned the packet around. Just as node zero needed to ARP
for the MAC address of node one, now node one must ARP for the MAC address of
node zero. We see the ARP request enqueued on the transmit queue of node one;
then we see the ARP request dequeued from the tranmit queue of node one (and
implicitly transmitted to node zero). Then we see an ARP response enqueued
on the transmit queue of node zero; and finally the ARP response dequeued (and
implicitly transmitted back to node one).
This exchange is summarized in the following trace event excerpts,
@verbatim
+ 2.00786 nodeid=1 ... ARP(request ...
- 2.00786 nodeid=1 ... ARP(request ...
+ 2.00994 nodeid=0 ... ARP(reply ...
- 2.00994 nodeid=0 ... ARP(reply ...
@end verbatim
The final two trace events in the @code{tutorial.tr} file correspond to the
echoed packet being enqueued for transmission on the net device for node one,
and that packet being dequeued (and implicitly transmitted back to node zero).
@cindex AsciiTrace!TraceAllNetDeviceRx
@cindex ARP!request
If you look at the trace file (@code{tutorial.tr}) you will also see some
entries with an @code{r} event, indicating a
@emph{receive} trace event. Recall that the first packet sent on the network
was a broadcast ARP request. We should then see all four nodes receive a
copy of this request. This is the case, as the first four receive trace
events are,
@verbatim
r 2.00207 nodeid=0 device=0 dev-rx pkt-uid=9 ARP(request ...
r 2.00207 nodeid=1 device=0 dev-rx pkt-uid=9 ARP(request ...
r 2.00207 nodeid=2 device=0 dev-rx pkt-uid=9 ARP(request ...
r 2.00207 nodeid=3 device=0 dev-rx pkt-uid=9 ARP(request ...
@end verbatim
@cindex unique ID
You can see that a copy of the broadcast packet with unique ID 9 was received
by the net devices on nodes 0, 1, 2 and 3. We leave it up to you to parse the
rest of the trace file and understand the remaining reception events.
@subsection PCAP Trace Wrapper
@cindex pcap
@cindex Wireshark
The @command{ns-3} @emph{pcap trace wrapper} is used to create trace files in
@code{.pcap} format. The acronym pcap (usually written in lower case) stands
for @emph{p}acket @emph{cap}ture, and is actually an API that includes the
definition of a @code{.pcap} file format. The most popular program that can
read and display this format is Wireshark (formerly called Ethereal).
However, there are many traffic trace analyzers that use this packet
format, including X, Y, and Z. We encourage users to exploit the
many tools available for analyzing pcap traces; below, we show how
tcpdump and Wireshark can be used..
@cindex tutorial-csma-echo-ascii-trace.cc
@cindex tutorial-csma-echo-pcap-trace.cc
The code used to enable pcap tracing is similar to that for ASCII tracing.
We have provided another file, @code{tutorial-csma-echo-pcap-trace.cc} that
uses the pcap trace wrapper. We have added the code to include the pcap
trace wrapper defintions:
@verbatim
#include "ns3/pcap-trace.h"
@end verbatim
And then added the following code below the AsciiTrace methods:
@cindex PcapTrace
@cindex PcapTrace!TraceAllIp
@verbatim
PcapTrace pcaptrace ("tutorial.pcap");
pcaptrace.TraceAllIp ();
@end verbatim
The first line of the code immediately above declares an object of type
@code{PcapTrace} named @code{pcaptrace} and passes a string parameter to its
constructor. This object is used to hide the details of the actual tracing
subsystem. The parameter is a base file name from which the actual trace file
names will be built. The second line of code tells the @code{PcamTrace}
object to trace all IP activity in all of the nodes present in the simulation.
@cindex interface index
Trace files are not created until trace activity is detected. Each file name
is composed of the base file name, followed by a @code{'-'}, a node id followed
by a @code{'-}', and an IP interface index. You will soon see a file named
@code{tutorial.pcap-0-1}, for example. This will be the trace file generated
as events are detected on node zero, interface index one. N.B. Interface
indices are different that net device indices --- interface index zero
corresponds to the loopback interface and interface index one corresponds to
the first net device you added to a node.
You may run the new program just like all of the others so far:
@cindex Waf
@verbatim
./waf --run tutorial-csma-echo-pcap-trace
@end verbatim
If you look at the top level directory of your distribution, you should now
see three log files: @code{tutorial.tr} is the ASCII trace file we have
previously examined. @code{tutorial.pcap-0-1} and @code{tutorial.pcap-1-1}
are the new pcap files we just generated. There will not be files
corresponding to nodes two and three since we have not sent any IP packets to
those nodes.
@subsubsection Reading output with tcpdump
@cindex tcpdump
@subsubsection Reading output with Wireshark
@cindex Wireshark
If you are unfamilar with Wireshark, there is a web site available from which
you can download programs and documentation: @uref{http://www.wireshark.org/}.
If you have Wireshark available, you can open each of the trace files and
display the contents as if you had captured the packets using a
@emph{packet sniffer}. Note that only IP packets are traced using this
wrapper, so you will not see the ARP exchanges that were logged when using
the ASCII trace wrapper. You are encouraged to take a look at the contents
of these pcap files using your favorite pcap software (or Wireshark).
@node Logging
@section Logging
@node Statistics
@section Statistics
@node Advanced Tracing
@section Advanced Tracing
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

+373
View File
@@ -0,0 +1,373 @@
@node ns-3 routing overview
@chapter ns-3 routing overview
This chapter describes the overall design of routing in the
@code{src/internet-node}
module, and some details about the routing approachs currently
implemented.
@node Routing-Overview
@section Overview
We intend to support traditional routing approaches and protocols,
ports of open source routing implementations, and facilitate research
into unorthodox routing techniques.
For simulations that are not primarily focused on routing and that
simply want correct routing tables to occur somehow, we have an
global centralized routing capability. A singleton object
(GlobalRouteManager) be instantiated, builds a network map, and
populates a forwarding table on each node at time t=0 in the
simulation. Simulation script writers can use the same node
API to manually enter routes as well.
@node Support for multiple routing protocols
@section Support for multiple routing protocols
Typically, multiple routing protocols are supported in user space and
coordinate to write a single forwarding table in the kernel. Presently
in @command{ns-3}, the implementation instead allows for multiple routing
protocols to build/keep their own routing state, and the IPv4 implementation
will query each one of these routing protocols (in some order determined
by the simulation author) until a route is found.
We chose this approach because it may better
faciliate the integration of disparate routing approaches that may
be difficult to coordinate the writing to a single table, approaches
where more information than destination IP address (e.g., source
routing) is used to determine the next hop, and on-demand
routing approaches where packets must be cached.
There are presently two routing protocols defined:
@itemize @bullet
@item class Ipv4StaticRouting (covering both unicast and multicast)
@item Optimized Link State Routing (a MANET protocol defined in
@uref{http://www.ietf.org/rfc/rfc3626.txt,,RFC 3626})
@end itemize
but first we describe how multiple routing protocols are supported.
@subsection class Ipv4RoutingProtocol
@code{class Ipv4RoutingProtocol} derives from ns-3 Object which means
that it supports interface aggregation and reference counting. Routing
protocols should inherit from this class, defined in src/node/ipv4.cc.
The main function that must be supported by these protocols is called
@code{RequestRoute}.
@verbatim
* This method is called whenever a node's IPv4 forwarding engine
* needs to lookup a route for a given packet and IP header.
*
* The routing protocol implementation may determine immediately it
* should not be handling this particular the route request. For
* instance, a routing protocol may decline to search for routes for
* certain classes of addresses, like link-local. In this case,
* RequestRoute() should return false and the routeReply callback
* must not be invoked.
*
* If the routing protocol implementations assumes it can provide
* the requested route, then it should return true, and the
* routeReply callback must be invoked, either immediately before
* returning true (synchronously), or in the future (asynchronous).
* The routing protocol may use any information available in the IP
* header and packet as routing key, although most routing protocols
* use only the destination address (as given by
* ipHeader.GetDestination ()). The routing protocol is also
* allowed to add a new header to the packet, which will appear
* immediately after the IP header, although most routing do not
* insert any extra header.
*/
virtual bool RequestRoute (uint32_t ifIndex,
const Ipv4Header &ipHeader,
Ptr<Packet> packet,
RouteReplyCallback routeReply) = 0;
@end verbatim
This class also provides a typedef (used above) for a special Callback
that will pass to the callback function the Ipv4Route that is found (see the
Doxygen documentation):
@verbatim
typedef Callback<void, bool, const Ipv4Route&, Ptr<Packet>, const Ipv4Header&> RouteReplyCallback;
@end verbatim
@subsection Ipv4::AddRoutingProtocol
Class Ipv4 provides a pure virtual function declaration for the
method that allows one to add a routing protocol:
@verbatim
void AddRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol,
int16_t priority);
@end verbatim
This method is implemented by class Ipv4L3Protocol in the internet-node
module.
The priority variable above governs the priority in which the routing
protocols are inserted. Notice that it is a signed int.
When the class Ipv4L3Protocol is instantiated, a single routing
protocol (Ipv4StaticRouting, introduced below) is added at priority
zero. Internally, a list of Ipv4RoutingProtocols is stored, and
and the routing protocols are each consulted in decreasing order
of priority to see whether a match is found. Therefore, if you
want your Ipv4RoutingProtocol to have priority lower than the static
routing, insert it with priority less than 0; e.g.:
@verbatim
m_ipv4->AddRoutingProtocol (m_routingTable, -10);
@end verbatim
@subsection Ipv4L3Protocol::Lookup
The main function for obtaining a route is shown below:
@verbatim
Ipv4L3Protocol::Lookup (
uint32_t ifIndex,
Ipv4Header const &ipHeader,
Ptr<Packet> packet,
Ipv4RoutingProtocol::RouteReplyCallback routeReply)
@end verbatim
This function will search the list of routing protocols, in priority order,
until a route is found. It will then invoke the RouteReplyCallback
and no further routing protocols will be searched. If the caller does
not want to constrain the possible interface, it can be wildcarded
as such:
@verbatim
Lookup (Ipv4RoutingProtocol::IF_INDEX_ANY, ipHeader, packet, routeReply);
@end verbatim
@node Roadmap and Future work
@section Roadmap and Future work
Some goals for future support are:
Users should be able to trace (either debug print, or redirect to a trace
file) the routing table in a format such as used in an
Unix implementation:
@verbatim
# netstat -nr (or # route -n)
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
127.0.0.1 * 255.255.255.255 UH 0 0 0 lo
172.16.1.0 * 255.255.255.0 U 0 0 0 eth0
172.16.2.0 172.16.1.1 255.255.255.0 UG 0 0 0 eth0
# ip route show
192.168.99.0/24 dev eth0 scope link
127.0.0.0/8 dev lo scope link
default via 192.168.99.254 dev eth0
@end verbatim
Global computation of multicast routing should be implemented as well.
This would ignore group membership and ensure that a copy of every
sourced multicast datagram would be delivered to each node.
This might be implemented as an RPF mechanism that functioned on-demand
by querying the forwarding table,
and perhaps optimized by a small multicast forwarding cache. It is
a bit trickier to implement over wireless links where the input
interface is the same as the output interface; other aspects of the
packet must be considered and the forwarding logic slightly changed
to allow for forwarding out the same interface.
In the future, work on bringing XORP or quagga routing to ns, but it will
take several months to port and enable.
There are presently no roadmap plans for IPv6.
@node Static routing
@section Static routing
The internet-node module provides one routing protocol (Ipv4StaticRouting)
by default. This routing protocol allows one to add unicast or multicast
static routes to a node.
@node Unicast routing
@section Unicast routing
The unicast static routing API may be accessed via the functions
@verbatim
void Ipv4::AddHostRouteTo ()
void Ipv4::AddNetworkRouteTo ()
void Ipv4::SetDefaultRoute ()
uint32_t Ipv4::GetNRoutes ()
Ipv4Route Ipv4::GetRoute ()
@end verbatim
@uref{http://www.nsnam.org/doxygen/index.html,,Doxygen} documentation
provides full documentation of these methods. These methods are forwarding
functions to the actual implementation in Ipv4StaticRouting, when using
the internet-node module.
@node Multicast routing
@section Multicast routing
The following function is used to add a static multicast route
to a node:
@verbatim
void
Ipv4StaticRouting::AddMulticastRoute (Ipv4Address origin,
Ipv4Address group,
uint32_t inputInterface,
std::vector<uint32_t> outputInterfaces);
@end verbatim
A multicast route must specify an origin IP address, a multicast group and
an input network interface index as conditions and provide a vector of
output network interface indices over which packets matching the conditions
are sent.
Typically there are two main types of multicast routes: routes of the
first kind are used during forwarding. All of the conditions must be
exlicitly provided. The second kind of routes are used to get packets off
of a local node. The difference is in the input interface. Routes for
forwarding will always have an explicit input interface specified. Routes
off of a node will always set the input interface to a wildcard specified
by the index Ipv4RoutingProtocol::IF\_INDEX\_ANY.
For routes off of a local node wildcards may be used in the origin and
multicast group addresses. The wildcard used for Ipv4Adresses is that
address returned by Ipv4Address::GetAny () -- typically "0.0.0.0". Usage
of a wildcard allows one to specify default behavior to varying degrees.
For example, making the origin address a wildcard, but leaving the
multicast group specific allows one (in the case of a node with multiple
interfaces) to create different routes using different output interfaces
for each multicast group.
If the origin and multicast addresses are made wildcards, you have created
essentially a default multicast address that can forward to multiple
interfaces. Compare this to the actual default multicast address that is
limited to specifying a single output interface for compatibility with
existing functionality in other systems.
Another command sets the default multicast route:
@verbatim
void
Ipv4StaticRouting::SetDefaultMulticastRoute (uint32_t outputInterface);
@end verbatim
This is the multicast equivalent of the unicast version SetDefaultRoute.
We tell the routing system what to do in the case where a specific route
to a destination multicast group is not found. The system forwards
packets out the specified interface in the hope that "something out there"
knows better how to route the packet. This method is only used in
initially sending packets off of a host. The default multicast route is
not consulted during forwarding -- exact routes must be specified using
AddMulticastRoute for that case.
Since we're basically sending packets to some entity we think may know
better what to do, we don't pay attention to "subtleties" like origin
address, nor do we worry about forwarding out multiple interfaces. If the
default multicast route is set, it is returned as the selected route from
LookupStatic irrespective of origin or multicast group if another specific
route is not found.
Finally, a number of additional functions are provided to fetch and
remove multicast routes:
@verbatim
uint32_t GetNMulticastRoutes (void) const;
Ipv4MulticastRoute *GetMulticastRoute (uint32_t i) const;
Ipv4MulticastRoute *GetDefaultMulticastRoute (void) const;
bool RemoveMulticastRoute (Ipv4Address origin,
Ipv4Address group,
uint32_t inputInterface);
void RemoveMulticastRoute (uint32_t index);
@end verbatim
@node Global centralized routing
@section Global centralized routing
Presently, global centralized IPv4 @emph{unicast} routing over both
point-to-point and shared (CSMA) links is supported.
The global centralized routing will be modified in the future to
reduce computations once profiling finds the performance bottlenecks.
@node Global Unicast Routing API
@section Global Unicast Routing API
The public API is very minimal. User scripts include the following:
@verbatim
#include "ns3/global-route-manager.h"
@end verbatim
After IP addresses are configured, the following function call will
cause all of the nodes that have an Ipv4 interface to receive
forwarding tables entered automatically by the GlobalRouteManager:
@verbatim
GlobalRouteManager::PopulateRoutingTables ();
@end verbatim
@emph{Note:} A reminder that the wifi NetDevice is not yet supported
(only CSMA and PointToPoint).
@node Global Routing Implementation
@section Global Routing Implementation
A singleton object (GlobalRouteManager) is responsible for populating
the static routes on each node, using the public Ipv4 API of that node.
It queries each node in the topology for a "globalRouter" interface.
If found, it uses the API of that interface to obtain a "link state
advertisement (LSA)" for the router. Link State Advertisements
are used in OSPF routing, and we follow their formatting.
The GlobalRouteManager populates a link state database with LSAs
gathered from the entire topology. Then, for each router in the topology,
the GlobalRouteManager executes the OSPF shortest path first (SPF)
computation on the database, and populates the routing tables on each
node.
The quagga (http://www.quagga.net) OSPF implementation was used as the
basis for the routing computation logic.
One benefit of following an existing OSPF SPF implementation is that
OSPF already has defined link state advertisements for all common
types of network links:
@itemize @bullet
@item point-to-point (serial links)
@item point-to-multipoint (Frame Relay, ad hoc wireless)
@item non-broadcast multiple access (ATM)
@item broadcast (Ethernet)
@end itemize
Therefore, we think that enabling these other link types will be more
straightforward now that the underlying OSPF SPF framework is in place.
Presently, we can handle IPv4 point-to-point, numbered links, as well
as shared broadcast (CSMA) links, and we do not do equal-cost multipath.
The GlobalRouteManager first walks the list of nodes and aggregates
a GlobalRouter interface to each one as follows:
@verbatim
typedef std::vector < Ptr<Node> >::iterator Iterator;
for (Iterator i = NodeList::Begin (); i != NodeList::End (); i++)
{
Ptr<Node> node = *i;
Ptr<GlobalRouter> globalRouter = CreateObject<GlobalRouter> (node);
node->AggregateObject (globalRouter);
}
@end verbatim
This interface is later queried and used to generate a Link State
Advertisement for each router, and this link state database is
fed into the OSPF shortest path computation logic. The Ipv4 API
is finally used to populate the routes themselves.
@node Optimized Link State Routing (OLSR)
@section Optimized Link State Routing (OLSR)
This is the first dynamic routing protocol for @command{ns-3}. The implementation
is found in the src/routing/olsr directory, and an example script is in
examples/simple-point-to-point-olsr.cc.
The following commands will enable OLSR in a simulation.
@verbatim
olsr::EnableAllNodes (); // Start OLSR on all nodes
olsr::EnableNodes(InputIterator begin, InputIterator end); // Start on
// a list of nodes
olsr::EnableNode (Ptr<Node> node); // Start OLSR on "node" only
@end verbatim
Once instantiated, the agent can be started with the Start() command,
and the OLSR "main interface" can be set with the SetMainInterface()
command. A number of protocol constants are defined in olsr-agent-impl.cc.
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

+82
View File
@@ -0,0 +1,82 @@
@node Troubleshooting
@chapter Troubleshooting
This chapter posts some information about possibly common errors in building
or running ns-3 programs.
Please note that the wiki (@uref{http://www.nsnam.org/wiki/index.php/Troubleshooting}) may have contributed items.
@node Build errors
@section Build errors
@node Run-time errors
@section Run-time errors
Sometimes, errors can occur with a program after a successful build. These
are run-time errors, and can commonly occur when memory is corrupted or
pointer values are unexpectedly null.
Here is an example of what might occur:
@verbatim
ns-old:~/ns-3-nsc$ ./waf --run tcp-point-to-point
Entering directory `/home/tomh/ns-3-nsc/build'
Compilation finished successfully
Command ['/home/tomh/ns-3-nsc/build/debug/examples/tcp-point-to-point'] exited with code -11
@end verbatim
The error message says that the program terminated unsuccessfully, but it is
not clear from this information what might be wrong. To examine more
closely, try running it under the @uref{http://sources.redhat.com/gdb/,,gdb debugger}:
@verbatim
ns-old:~/ns-3-nsc$ ./waf --run tcp-point-to-point --command-template="gdb %s"
Entering directory `/home/tomh/ns-3-nsc/build'
Compilation finished successfully
GNU gdb Red Hat Linux (6.3.0.0-1.134.fc5rh)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu"...Using host libthread_db library "/lib/libthread_db.so.1".
(gdb) run
Starting program: /home/tomh/ns-3-nsc/build/debug/examples/tcp-point-to-point
Reading symbols from shared object read from target memory...done.
Loaded system supplied DSO at 0xf5c000
Program received signal SIGSEGV, Segmentation fault.
0x0804aa12 in main (argc=1, argv=0xbfdfefa4)
at ../examples/tcp-point-to-point.cc:136
136 Ptr<Socket> localSocket = socketFactory->CreateSocket ();
(gdb) p localSocket
$1 = {m_ptr = 0x3c5d65}
(gdb) p socketFactory
$2 = {m_ptr = 0x0}
(gdb) quit
The program is running. Exit anyway? (y or n) y
@end verbatim
Note first the way the program was invoked-- pass the command to run as
an argument to the command template "gdb %s".
This tells us that there was an attempt to dereference a null pointer
socketFactory.
Let's look around line 136 of tcp-point-to-point, as gdb suggests:
@verbatim
Ptr<SocketFactory> socketFactory = n2->GetObject<SocketFactory> (Tcp::iid);
Ptr<Socket> localSocket = socketFactory->CreateSocket ();
localSocket->Bind ();
@end verbatim
The culprit here is that the return value of GetObject is not being
checked and may be null.
Sometimes you may need to use the @uref{http://valgrind.org,,valgrind memory
checker} for more subtle errors. Again, you invoke the use of valgrind
similarly:
@verbatim
ns-old:~/ns-3-nsc$ ./waf --run tcp-point-to-point --command-template="valgrind %s"
@end verbatim
+111
View File
@@ -0,0 +1,111 @@
\input texinfo @c -*-texinfo-*-
@c %**start of header
@setfilename ns-3.info
@settitle ns-3 tutorial
@c @setchapternewpage odd
@c %**end of header
@ifinfo
Primary documentation for the @command{ns-3} project is available in
three forms:
@itemize @bullet
@item @uref{http://www.nsnam.org/doxygen/index.html,,ns-3 Doxygen/Manual}: Documentation of the public APIs of the simulator
@item Tutorial (this document)
@item @uref{http://www.nsnam.org/wiki/index.php,, ns-3 wiki}
@end itemize
This document is written in GNU Texinfo and is to be maintained in
revision control on the @command{ns-3} code server. Both PDF and HTML versions
should be available on the server. Changes to
the document should be discussed on the ns-developers@@isi.edu mailing list.
@end ifinfo
@copying
This is an @command{ns-3} tutorial.
Primary documentation for the @command{ns-3} project is available in
three forms:
@itemize @bullet
@item @uref{http://www.nsnam.org/doxygen/index.html,,ns-3 Doxygen/Manual}: Documentation of the public APIs of the simulator
@item Tutorial (this document)
@item @uref{http://www.nsnam.org/wiki/index.php,, ns-3 wiki}
@end itemize
This document is written in GNU Texinfo and is to be maintained in
revision control on the @command{ns-3} code server. Both PDF and HTML
versions should be available on the server. Changes to
the document should be discussed on the ns-developers@@isi.edu mailing list.
This software 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 software 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, see @uref{http://www.gnu.org/licenses/}.
@end copying
@titlepage
@title ns-3 Tutorial
@author ns-3 project
@author feedback: ns-developers@@isi.edu
@today{}
@c @page
@vskip 0pt plus 1filll
@insertcopying
@end titlepage
@c So the toc is printed at the start.
@anchor{Full Table of Contents}
@contents
@ifnottex
@node Top, Overview, Full Table of Contents
@top ns-3 Tutorial (html version)
For a pdf version of this tutorial,
see @uref{http://www.nsnam.org/docs/tutorial.pdf}.
@insertcopying
@end ifnottex
@menu
* Tutorial Goals::
Part 1: Getting Started with ns-3
* Overview::
* Browsing::
* Resources::
* Downloading and Compiling::
* Some-Prerequisites::
* A-First-ns-3-Script::
Part 2-: Details
* ns-3 Callbacks::
* Simulation Output::
* ns-3 routing overview::
* Other-network-topologies::
* Nonlinear-Thinking::
* Summary::
* Object-Model::
* The-Doxygen-Documentation-System::
* How-To-Change-Things::
* How-To-Set-Default-Values::
* How-To-Write-A-New-Application::
@ Troubleshooting
@end menu
@include introduction.texi
@include callbacks.texi
@include output.texi
@include routing.texi
@include other.texi
@include troubleshoot.texi
@printindex cp
@bye
+6 -6
View File
@@ -107,9 +107,9 @@ main (int argc, char *argv[])
// Here, we will explicitly create four nodes. In more sophisticated
// topologies, we could configure a node factory.
NS_LOG_INFO ("Create nodes.");
Ptr<Node> n0 = Create<InternetNode> ();
Ptr<Node> n1 = Create<InternetNode> ();
Ptr<Node> n2 = Create<InternetNode> ();
Ptr<Node> n0 = CreateObject<InternetNode> ();
Ptr<Node> n1 = CreateObject<InternetNode> ();
Ptr<Node> n2 = CreateObject<InternetNode> ();
// We create the channels first without any IP addressing information
NS_LOG_INFO ("Create channels.");
@@ -154,7 +154,7 @@ main (int argc, char *argv[])
// Create the OnOff application to send UDP datagrams of size
// 512 bytes (default) at a rate of 500 Kb/s (default) from n0
NS_LOG_INFO ("Create Applications.");
Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
Ptr<OnOffApplication> ooff = CreateObject<OnOffApplication> (
n0,
InetSocketAddress ("255.255.255.255", port),
"Udp",
@@ -165,7 +165,7 @@ main (int argc, char *argv[])
ooff->Stop (Seconds(10.0));
// Create an optional packet sink to receive these packets
Ptr<PacketSink> sink = Create<PacketSink> (
Ptr<PacketSink> sink = CreateObject<PacketSink> (
n1,
InetSocketAddress (Ipv4Address::GetAny (), port),
"Udp");
@@ -174,7 +174,7 @@ main (int argc, char *argv[])
sink->Stop (Seconds (10.0));
// Create an optional packet sink to receive these packets
sink = Create<PacketSink> (
sink = CreateObject<PacketSink> (
n2,
InetSocketAddress (Ipv4Address::GetAny (), port),
"Udp");
+10 -10
View File
@@ -106,11 +106,11 @@ main (int argc, char *argv[])
// Explicitly create the nodes required by the topology (shown above).
//
NS_LOG_INFO ("Create nodes.");
Ptr<Node> n0 = Create<InternetNode> ();
Ptr<Node> n1 = Create<InternetNode> ();
Ptr<Node> n2 = Create<InternetNode> ();
Ptr<Node> n3 = Create<InternetNode> ();
Ptr<Node> n4 = Create<InternetNode> ();
Ptr<Node> n0 = CreateObject<InternetNode> ();
Ptr<Node> n1 = CreateObject<InternetNode> ();
Ptr<Node> n2 = CreateObject<InternetNode> ();
Ptr<Node> n3 = CreateObject<InternetNode> ();
Ptr<Node> n4 = CreateObject<InternetNode> ();
NS_LOG_INFO ("Create channels.");
//
@@ -211,7 +211,7 @@ main (int argc, char *argv[])
// a fine time to find the interface indices on node two.
//
Ptr<Ipv4> ipv4;
ipv4 = n2->QueryInterface<Ipv4> (Ipv4::iid);
ipv4 = n2->GetObject<Ipv4> ();
uint32_t ifIndexLan0 = ipv4->FindInterfaceForAddr (n2Lan0Addr);
uint32_t ifIndexLan1 = ipv4->FindInterfaceForAddr (n2Lan1Addr);
@@ -261,7 +261,7 @@ main (int argc, char *argv[])
// interface to find the output interface index, and tell node zero to send
// its multicast traffic out that interface.
//
ipv4 = n0->QueryInterface<Ipv4> (Ipv4::iid);
ipv4 = n0->GetObject<Ipv4> ();
uint32_t ifIndexSrc = ipv4->FindInterfaceForAddr (multicastSource);
ipv4->SetDefaultMulticastRoute (ifIndexSrc);
//
@@ -269,7 +269,7 @@ main (int argc, char *argv[])
// multicast data. To enable forwarding bits up the protocol stack, we need
// to tell the stack to join the multicast group.
//
ipv4 = n4->QueryInterface<Ipv4> (Ipv4::iid);
ipv4 = n4->GetObject<Ipv4> ();
ipv4->JoinMulticastGroup (multicastSource, multicastGroup);
//
// Create an OnOff application to send UDP datagrams from node zero to the
@@ -281,7 +281,7 @@ main (int argc, char *argv[])
// Configure a multicast packet generator that generates a packet
// every few seconds
Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
Ptr<OnOffApplication> ooff = CreateObject<OnOffApplication> (
n0,
InetSocketAddress (multicastGroup, port),
"Udp",
@@ -298,7 +298,7 @@ main (int argc, char *argv[])
// Create an optional packet sink to receive these packets
// If you enable logging on this (above) it will print a log statement
// for every packet received
Ptr<PacketSink> sink = Create<PacketSink> (
Ptr<PacketSink> sink = CreateObject<PacketSink> (
n4,
InetSocketAddress (Ipv4Address::GetAny (), port),
"Udp");
+6 -6
View File
@@ -100,10 +100,10 @@ main (int argc, char *argv[])
// Explicitly create the nodes required by the topology (shown above).
//
NS_LOG_INFO ("Create nodes.");
Ptr<Node> n0 = Create<InternetNode> ();
Ptr<Node> n1 = Create<InternetNode> ();
Ptr<Node> n2 = Create<InternetNode> ();
Ptr<Node> n3 = Create<InternetNode> ();
Ptr<Node> n0 = CreateObject<InternetNode> ();
Ptr<Node> n1 = CreateObject<InternetNode> ();
Ptr<Node> n2 = CreateObject<InternetNode> ();
Ptr<Node> n3 = CreateObject<InternetNode> ();
NS_LOG_INFO ("Create channels.");
//
@@ -165,7 +165,7 @@ main (int argc, char *argv[])
//
NS_LOG_INFO ("Create Applications.");
uint16_t port = 9; // Discard port (RFC 863)
Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
Ptr<OnOffApplication> ooff = CreateObject<OnOffApplication> (
n0,
InetSocketAddress ("10.1.1.2", port),
"Udp",
@@ -179,7 +179,7 @@ main (int argc, char *argv[])
//
// Create a similar flow from n3 to n0, starting at time 1.1 seconds
//
ooff = Create<OnOffApplication> (
ooff = CreateObject<OnOffApplication> (
n3,
InetSocketAddress ("10.1.1.1", port),
"Udp",
+8 -8
View File
@@ -61,7 +61,7 @@ NS_LOG_COMPONENT_DEFINE ("CsmaPacketSocketExample");
static Ptr<CsmaNetDevice>
CreateCsmaDevice (Ptr<Node> node, Ptr<CsmaChannel> channel)
{
Ptr<CsmaNetDevice> device = Create<CsmaNetDevice> (node);
Ptr<CsmaNetDevice> device = CreateObject<CsmaNetDevice> (node);
device->Attach (channel);
Ptr<Queue> queue = Queue::CreateDefault ();
device->AddQueue (queue);
@@ -102,14 +102,14 @@ main (int argc, char *argv[])
// Here, we will explicitly create four nodes. In more sophisticated
// topologies, we could configure a node factory.
NS_LOG_INFO ("Create nodes.");
Ptr<Node> n0 = Create<Node> ();
Ptr<Node> n1 = Create<Node> ();
Ptr<Node> n2 = Create<Node> ();
Ptr<Node> n3 = Create<Node> ();
Ptr<Node> n0 = CreateObject<Node> ();
Ptr<Node> n1 = CreateObject<Node> ();
Ptr<Node> n2 = CreateObject<Node> ();
Ptr<Node> n3 = CreateObject<Node> ();
// create the shared medium used by all csma devices.
NS_LOG_INFO ("Create channels.");
Ptr<CsmaChannel> channel = Create<CsmaChannel> (DataRate(5000000), MilliSeconds(2));
Ptr<CsmaChannel> channel = CreateObject<CsmaChannel> (DataRate(5000000), MilliSeconds(2));
// use a helper function to connect our nodes to the shared channel.
NS_LOG_INFO ("Build Topology.");
@@ -134,7 +134,7 @@ main (int argc, char *argv[])
// 210 bytes at a rate of 448 Kb/s
// from n0 to n1
NS_LOG_INFO ("Create Applications.");
Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
Ptr<OnOffApplication> ooff = CreateObject<OnOffApplication> (
n0,
n0ToN1,
"Packet",
@@ -145,7 +145,7 @@ main (int argc, char *argv[])
ooff->Stop (Seconds(10.0));
// Create a similar flow from n3 to n0, starting at time 1.1 seconds
ooff = Create<OnOffApplication> (
ooff = CreateObject<OnOffApplication> (
n3,
n3ToN0,
"Packet",
+8 -8
View File
@@ -120,13 +120,13 @@ main (int argc, char *argv[])
CommandLine::Parse (argc, argv);
NS_LOG_INFO ("Create nodes.");
Ptr<Node> n0 = Create<InternetNode> ();
Ptr<Node> n1 = Create<InternetNode> ();
Ptr<Node> n2 = Create<InternetNode> ();
Ptr<Node> n3 = Create<InternetNode> ();
Ptr<Node> n4 = Create<InternetNode> ();
Ptr<Node> n5 = Create<InternetNode> ();
Ptr<Node> n6 = Create<InternetNode> ();
Ptr<Node> n0 = CreateObject<InternetNode> ();
Ptr<Node> n1 = CreateObject<InternetNode> ();
Ptr<Node> n2 = CreateObject<InternetNode> ();
Ptr<Node> n3 = CreateObject<InternetNode> ();
Ptr<Node> n4 = CreateObject<InternetNode> ();
Ptr<Node> n5 = CreateObject<InternetNode> ();
Ptr<Node> n6 = CreateObject<InternetNode> ();
// We create the channels first without any IP addressing information
NS_LOG_INFO ("Create channels.");
@@ -191,7 +191,7 @@ main (int argc, char *argv[])
// 210 bytes at a rate of 448 Kb/s
NS_LOG_INFO ("Create Applications.");
uint16_t port = 9; // Discard port (RFC 863)
Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
Ptr<OnOffApplication> ooff = CreateObject<OnOffApplication> (
n0,
InetSocketAddress ("10.1.3.2", port),
"Udp",
+6 -6
View File
@@ -128,10 +128,10 @@ main (int argc, char *argv[])
// Here, we will explicitly create four nodes. In more sophisticated
// topologies, we could configure a node factory.
NS_LOG_INFO ("Create nodes.");
Ptr<Node> n0 = Create<InternetNode> ();
Ptr<Node> n1 = Create<InternetNode> ();
Ptr<Node> n2 = Create<InternetNode> ();
Ptr<Node> n3 = Create<InternetNode> ();
Ptr<Node> n0 = CreateObject<InternetNode> ();
Ptr<Node> n1 = CreateObject<InternetNode> ();
Ptr<Node> n2 = CreateObject<InternetNode> ();
Ptr<Node> n3 = CreateObject<InternetNode> ();
// We create the channels first without any IP addressing information
NS_LOG_INFO ("Create channels.");
@@ -182,7 +182,7 @@ main (int argc, char *argv[])
uint16_t port = 9; // Discard port (RFC 863)
// Create a flow from n3 to n1, starting at time 1.1 seconds
Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
Ptr<OnOffApplication> ooff = CreateObject<OnOffApplication> (
n3,
InetSocketAddress ("10.1.1.1", port),
"Udp",
@@ -193,7 +193,7 @@ main (int argc, char *argv[])
ooff->Stop (Seconds (10.0));
// Create a packet sink to receive these packets
Ptr<PacketSink> sink = Create<PacketSink> (
Ptr<PacketSink> sink = CreateObject<PacketSink> (
n1,
InetSocketAddress (Ipv4Address::GetAny (), port),
"Udp");
+12 -14
View File
@@ -52,7 +52,6 @@
#include "ns3/pcap-trace.h"
#include "ns3/internet-node.h"
#include "ns3/default-value.h"
#include "ns3/component-manager.h"
#include "ns3/random-variable.h"
#include "ns3/point-to-point-channel.h"
#include "ns3/point-to-point-net-device.h"
@@ -97,10 +96,10 @@ main (int argc, char *argv[])
// Here, we will explicitly create four nodes. In more sophisticated
// topologies, we could configure a node factory.
NS_LOG_INFO ("Create nodes.");
Ptr<Node> n0 = Create<InternetNode> ();
Ptr<Node> n1 = Create<InternetNode> ();
Ptr<Node> n2 = Create<InternetNode> ();
Ptr<Node> n3 = Create<InternetNode> ();
Ptr<Node> n0 = CreateObject<InternetNode> ();
Ptr<Node> n1 = CreateObject<InternetNode> ();
Ptr<Node> n2 = CreateObject<InternetNode> ();
Ptr<Node> n3 = CreateObject<InternetNode> ();
// We create the channels first without any IP addressing information
NS_LOG_INFO ("Create channels.");
@@ -143,7 +142,7 @@ main (int argc, char *argv[])
// 210 bytes at a rate of 448 Kb/s
NS_LOG_INFO ("Create Applications.");
uint16_t port = 9; // Discard port (RFC 863)
Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
Ptr<OnOffApplication> ooff = CreateObject<OnOffApplication> (
n0,
InetSocketAddress ("10.1.3.2", port),
"Udp",
@@ -154,7 +153,7 @@ main (int argc, char *argv[])
ooff->Stop (Seconds(10.0));
// Create an optional packet sink to receive these packets
Ptr<PacketSink> sink = Create<PacketSink> (
Ptr<PacketSink> sink = CreateObject<PacketSink> (
n3,
InetSocketAddress (Ipv4Address::GetAny (), port),
"Udp");
@@ -163,7 +162,7 @@ main (int argc, char *argv[])
sink->Stop (Seconds (10.0));
// Create a similar flow from n3 to n1, starting at time 1.1 seconds
ooff = Create<OnOffApplication> (
ooff = CreateObject<OnOffApplication> (
n3,
InetSocketAddress ("10.1.2.1", port),
"Udp",
@@ -174,7 +173,7 @@ main (int argc, char *argv[])
ooff->Stop (Seconds(10.0));
// Create a packet sink to receive these packets
sink = Create<PacketSink> (
sink = CreateObject<PacketSink> (
n1,
InetSocketAddress (Ipv4Address::GetAny (), port),
"Udp");
@@ -186,9 +185,9 @@ main (int argc, char *argv[])
// This will likely set by some global StaticRouting object in the future
NS_LOG_INFO ("Set Default Routes.");
Ptr<Ipv4> ipv4;
ipv4 = n0->QueryInterface<Ipv4> (Ipv4::iid);
ipv4 = n0->GetObject<Ipv4> ();
ipv4->SetDefaultRoute (Ipv4Address ("10.1.1.2"), 1);
ipv4 = n3->QueryInterface<Ipv4> (Ipv4::iid);
ipv4 = n3->GetObject<Ipv4> ();
ipv4->SetDefaultRoute (Ipv4Address ("10.1.3.1"), 1);
//
@@ -205,8 +204,7 @@ main (int argc, char *argv[])
NS_ASSERT (em != 0);
// Now, query interface on the resulting em pointer to see if a
// RateErrorModel interface exists. If so, set the packet error rate
Ptr<RateErrorModel> bem = em->QueryInterface<RateErrorModel>
(RateErrorModel::iid);
Ptr<RateErrorModel> bem = em->GetObject<RateErrorModel> ();
if (bem)
{
bem->SetRandomVariable (UniformVariable ());
@@ -222,7 +220,7 @@ main (int argc, char *argv[])
sampleList.push_back (11);
sampleList.push_back (17);
// This time, we'll explicitly create the error model we want
Ptr<ListErrorModel> pem = Create<ListErrorModel> ();
Ptr<ListErrorModel> pem = CreateObject<ListErrorModel> ();
pem->SetList (sampleList);
nd2->AddReceiveErrorModel (pem);
+8 -8
View File
@@ -122,10 +122,10 @@ main (int argc, char *argv[])
// Here, we will explicitly create four nodes. In more sophisticated
// topologies, we could configure a node factory.
NS_LOG_INFO ("Create nodes.");
Ptr<Node> n0 = Create<InternetNode> ();
Ptr<Node> n1 = Create<InternetNode> ();
Ptr<Node> n2 = Create<InternetNode> ();
Ptr<Node> n3 = Create<InternetNode> ();
Ptr<Node> n0 = CreateObject<InternetNode> ();
Ptr<Node> n1 = CreateObject<InternetNode> ();
Ptr<Node> n2 = CreateObject<InternetNode> ();
Ptr<Node> n3 = CreateObject<InternetNode> ();
// We create the channels first without any IP addressing information
NS_LOG_INFO ("Create channels.");
@@ -163,7 +163,7 @@ main (int argc, char *argv[])
// 210 bytes at a rate of 448 Kb/s
NS_LOG_INFO ("Create Applications.");
uint16_t port = 9; // Discard port (RFC 863)
Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
Ptr<OnOffApplication> ooff = CreateObject<OnOffApplication> (
n0,
InetSocketAddress ("10.1.3.2", port),
"Udp",
@@ -175,7 +175,7 @@ main (int argc, char *argv[])
// Create a packet sink to receive these packets
// The last argument "true" disables output from the Receive callback
Ptr<PacketSink> sink = Create<PacketSink> (
Ptr<PacketSink> sink = CreateObject<PacketSink> (
n3,
InetSocketAddress (Ipv4Address::GetAny (), port),
"Udp");
@@ -184,7 +184,7 @@ main (int argc, char *argv[])
sink->Stop (Seconds (10.0));
// Create a similar flow from n3 to n1, starting at time 1.1 seconds
ooff = Create<OnOffApplication> (
ooff = CreateObject<OnOffApplication> (
n3,
InetSocketAddress ("10.1.2.1", port),
"Udp",
@@ -195,7 +195,7 @@ main (int argc, char *argv[])
ooff->Stop (Seconds (10.0));
// Create a packet sink to receive these packets
sink = Create<PacketSink> (
sink = CreateObject<PacketSink> (
n1,
InetSocketAddress (Ipv4Address::GetAny (), port),
"Udp");
+28 -34
View File
@@ -21,10 +21,10 @@
//
// Network topology
//
// n0
// n0
// \ 5 Mb/s, 2ms
// \ 1.5Mb/s, 10ms
// n2 -------------------------n3
// n2 -------------------------n3---------n4
// /
// / 5 Mb/s, 2ms
// n1
@@ -118,10 +118,11 @@ main (int argc, char *argv[])
// Here, we will explicitly create four nodes. In more sophisticated
// topologies, we could configure a node factory.
NS_LOG_INFO ("Create nodes.");
Ptr<Node> n0 = Create<InternetNode> ();
Ptr<Node> n1 = Create<InternetNode> ();
Ptr<Node> n2 = Create<InternetNode> ();
Ptr<Node> n3 = Create<InternetNode> ();
Ptr<Node> n0 = CreateObject<InternetNode> ();
Ptr<Node> n1 = CreateObject<InternetNode> ();
Ptr<Node> n2 = CreateObject<InternetNode> ();
Ptr<Node> n3 = CreateObject<InternetNode> ();
Ptr<Node> n4 = CreateObject<InternetNode> ();
// We create the channels first without any IP addressing information
NS_LOG_INFO ("Create channels.");
@@ -136,6 +137,10 @@ main (int argc, char *argv[])
Ptr<PointToPointChannel> channel2 =
PointToPointTopology::AddPointToPointLink (
n2, n3, DataRate(1500000), MilliSeconds(10));
Ptr<PointToPointChannel> channel3 =
PointToPointTopology::AddPointToPointLink (
n3, n4, DataRate(1500000), MilliSeconds(10));
// Later, we add IP addresses.
NS_LOG_INFO ("Assign IP Addresses.");
@@ -151,65 +156,54 @@ main (int argc, char *argv[])
channel2, n2, Ipv4Address("10.1.3.1"),
n3, Ipv4Address("10.1.3.2"));
// Finally, we add static routes. These three steps (Channel and
// NetDevice creation, IP Address assignment, and routing) are
// separated because there may be a need to postpone IP Address
// assignment (emulation) or modify to use dynamic routing
PointToPointTopology::AddIpv4Addresses (
channel3, n3, Ipv4Address("10.1.4.1"),
n4, Ipv4Address("10.1.4.2"));
// Enable OLSR
NS_LOG_INFO ("Enabling OLSR Routing.");
olsr::EnableAllNodes ();
// Create the OnOff application to send UDP datagrams of size
// 210 bytes at a rate of 448 Kb/s
NS_LOG_INFO ("Create Applications.");
uint16_t port = 9; // Discard port (RFC 863)
Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
Ptr<OnOffApplication> ooff = CreateObject<OnOffApplication> (
n0,
InetSocketAddress ("10.1.3.2", port),
InetSocketAddress ("10.1.4.2", port),
"Udp",
ConstantVariable(1),
ConstantVariable(0));
// Start the application
ooff->Start(Seconds(1.0));
ooff->Stop (Seconds(10.0));
// Create an optional packet sink to receive these packets
Ptr<PacketSink> sink = Create<PacketSink> (
n3,
Ptr<PacketSink> sink = CreateObject<PacketSink> (
n4,
InetSocketAddress (Ipv4Address::GetAny (), port),
"Udp");
// Start the sink
sink->Start (Seconds (1.0));
sink->Stop (Seconds (10.0));
// Create a similar flow from n3 to n1, starting at time 1.1 seconds
ooff = Create<OnOffApplication> (
n3,
// Create a similar flow from n4 to n1, starting at time 1.1 seconds
ooff = CreateObject<OnOffApplication> (
n4,
InetSocketAddress ("10.1.2.1", port),
"Udp",
ConstantVariable(1),
ConstantVariable(0));
// Start the application
ooff->Start(Seconds(1.1));
ooff->Stop (Seconds(10.0));
ooff->Start (Seconds(1.1));
// Create a packet sink to receive these packets
sink = Create<PacketSink> (
sink = CreateObject<PacketSink> (
n1,
InetSocketAddress (Ipv4Address::GetAny (), port),
"Udp");
// Start the sink
sink->Start (Seconds (1.1));
sink->Stop (Seconds (10.0));
// Here, finish off packet routing configuration
// This will likely set by some global StaticRouting object in the future
NS_LOG_INFO ("Set Default Routes.");
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-point-to-point.tr file
NS_LOG_INFO ("Configure Tracing.");
@@ -226,8 +220,8 @@ main (int argc, char *argv[])
pcaptrace.TraceAllIp ();
NS_LOG_INFO ("Run Simulation.");
Simulator::StopAt (Seconds (10));
Simulator::Run ();
Simulator::StopAt (Seconds (30));
Simulator::Run ();
Simulator::Destroy ();
NS_LOG_INFO ("Done.");
}
+34 -41
View File
@@ -72,29 +72,7 @@ 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
LogComponentEnable ("SimplePointToPointExample", LOG_LEVEL_INFO);
LogComponentEnable("Object", LOG_LEVEL_ALL);
LogComponentEnable("Queue", LOG_LEVEL_ALL);
LogComponentEnable("DropTailQueue", LOG_LEVEL_ALL);
LogComponentEnable("Channel", LOG_LEVEL_ALL);
LogComponentEnable("CsmaChannel", LOG_LEVEL_ALL);
LogComponentEnable("NetDevice", LOG_LEVEL_ALL);
LogComponentEnable("CsmaNetDevice", LOG_LEVEL_ALL);
LogComponentEnable("Ipv4L3Protocol", LOG_LEVEL_ALL);
LogComponentEnable("PacketSocket", LOG_LEVEL_ALL);
LogComponentEnable("Socket", LOG_LEVEL_ALL);
LogComponentEnable("UdpSocket", LOG_LEVEL_ALL);
LogComponentEnable("UdpL4Protocol", LOG_LEVEL_ALL);
LogComponentEnable("Ipv4L3Protocol", LOG_LEVEL_ALL);
LogComponentEnable("Ipv4StaticRouting", LOG_LEVEL_ALL);
LogComponentEnable("Ipv4Interface", LOG_LEVEL_ALL);
LogComponentEnable("ArpIpv4Interface", LOG_LEVEL_ALL);
LogComponentEnable("Ipv4LoopbackInterface", LOG_LEVEL_ALL);
LogComponentEnable("OnOffApplication", LOG_LEVEL_ALL);
LogComponentEnable("PacketSinkApplication", LOG_LEVEL_ALL);
LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_ALL);
LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_ALL);
LogComponentEnable ("SimplePointToPointExample", LOG_LEVEL_ALL);
#endif
// Set up some default values for the simulation. Use the Bind()
@@ -108,8 +86,6 @@ main (int argc, char *argv[])
DefaultValue::Bind ("OnOffApplicationPacketSize", "210");
DefaultValue::Bind ("OnOffApplicationDataRate", "448kb/s");
//DefaultValue::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);
@@ -117,10 +93,10 @@ main (int argc, char *argv[])
// Here, we will explicitly create four nodes. In more sophisticated
// topologies, we could configure a node factory.
NS_LOG_INFO ("Create nodes.");
Ptr<Node> n0 = Create<InternetNode> ();
Ptr<Node> n1 = Create<InternetNode> ();
Ptr<Node> n2 = Create<InternetNode> ();
Ptr<Node> n3 = Create<InternetNode> ();
Ptr<Node> n0 = CreateObject<InternetNode> ();
Ptr<Node> n1 = CreateObject<InternetNode> ();
Ptr<Node> n2 = CreateObject<InternetNode> ();
Ptr<Node> n3 = CreateObject<InternetNode> ();
// We create the channels first without any IP addressing information
NS_LOG_INFO ("Create channels.");
@@ -163,27 +139,25 @@ main (int argc, char *argv[])
// 210 bytes at a rate of 448 Kb/s
NS_LOG_INFO ("Create Applications.");
uint16_t port = 9; // Discard port (RFC 863)
Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
Ptr<OnOffApplication> ooff = CreateObject<OnOffApplication> (
n0,
InetSocketAddress ("10.1.3.2", port),
"Udp",
ConstantVariable(1),
ConstantVariable(0));
// Start the application
ooff->Start(Seconds(1.0));
ooff->Stop (Seconds(10.0));
ooff->Start (Seconds(1.0));
// Create an optional packet sink to receive these packets
Ptr<PacketSink> sink = Create<PacketSink> (
Ptr<PacketSink> sink = CreateObject<PacketSink> (
n3,
InetSocketAddress (Ipv4Address::GetAny (), port),
"Udp");
// Start the sink
sink->Start (Seconds (1.0));
sink->Stop (Seconds (10.0));
// Create a similar flow from n3 to n1, starting at time 1.1 seconds
ooff = Create<OnOffApplication> (
ooff = CreateObject<OnOffApplication> (
n3,
InetSocketAddress ("10.1.2.1", port),
"Udp",
@@ -191,24 +165,43 @@ main (int argc, char *argv[])
ConstantVariable(0));
// Start the application
ooff->Start(Seconds(1.1));
ooff->Stop (Seconds(10.0));
// Create a packet sink to receive these packets
sink = Create<PacketSink> (
sink = CreateObject<PacketSink> (
n1,
InetSocketAddress (Ipv4Address::GetAny (), port),
"Udp");
// Start the sink
sink->Start (Seconds (1.1));
sink->Stop (Seconds (10.0));
// TCP
// Create a file transfer from n0 to n3, starting at time 1.2
uint16_t servPort = 500;
ooff = CreateObject<OnOffApplication> (
n0,
InetSocketAddress ("10.1.3.2", servPort),
"Tcp",
ConstantVariable(1),
ConstantVariable(0));
// Start the application
ooff->Start (Seconds(1.2));
ooff->Stop (Seconds(1.35));
// Create a packet sink to receive these TCP packets
sink = Create<PacketSink> (
n3,
InetSocketAddress (Ipv4Address::GetAny (), servPort),
"Tcp");
sink->Start (Seconds (1.2));
// Here, finish off packet routing configuration
// This will likely set by some global StaticRouting object in the future
NS_LOG_INFO ("Set Default Routes.");
Ptr<Ipv4> ipv4;
ipv4 = n0->QueryInterface<Ipv4> (Ipv4::iid);
ipv4 = n0->GetObject<Ipv4> ();
ipv4->SetDefaultRoute (Ipv4Address ("10.1.1.2"), 1);
ipv4 = n3->QueryInterface<Ipv4> (Ipv4::iid);
ipv4 = n3->GetObject<Ipv4> ();
ipv4->SetDefaultRoute (Ipv4Address ("10.1.3.1"), 1);
// Configure tracing of all enqueue, dequeue, and NetDevice receive events
@@ -227,7 +220,7 @@ main (int argc, char *argv[])
pcaptrace.TraceAllIp ();
NS_LOG_INFO ("Run Simulation.");
Simulator::StopAt (Seconds (10));
Simulator::StopAt (Seconds (3.0));
Simulator::Run ();
Simulator::Destroy ();
NS_LOG_INFO ("Done.");
+244
View File
@@ -0,0 +1,244 @@
/* -*- 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
*
*/
//
// Network topology
//
// 10Mb/s, 10ms 10Mb/s, 10ms
// n0-----------------n1-----------------n2
//
//
// - Tracing of queues and packet receptions to file
// "tcp-large-transfer-errors.tr"
// - pcap traces also generated in the following files
// "tcp-large-transfer-errors.pcap-$n-$i" where n and i represent node and interface numbers respectively
// Usage (e.g.): ./waf --run tcp-large-transfer-errors
#include <ctype.h>
#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/log.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/point-to-point-channel.h"
#include "ns3/point-to-point-net-device.h"
#include "ns3/ipv4-address.h"
#include "ns3/inet-socket-address.h"
#include "ns3/ipv4.h"
#include "ns3/socket.h"
#include "ns3/ipv4-route.h"
#include "ns3/point-to-point-topology.h"
#include "ns3/onoff-application.h"
#include "ns3/packet-sink.h"
#include "ns3/error-model.h"
#include "ns3/node-list.h"
#include "ns3/tcp.h"
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("TcpLargeTransferErrors");
void
ApplicationTraceSink (const TraceContext &context, Ptr<const Packet> packet,
const Address &addr)
{
// g_log is not declared in optimized builds
// should convert this to use of some other flag than the logging system
#ifdef NS3_LOG_ENABLE
if (!g_log.IsNoneEnabled ()) {
if (InetSocketAddress::IsMatchingType (addr) )
{
InetSocketAddress address = InetSocketAddress::ConvertFrom (addr);
std::cout << "PacketSink received size " <<
packet->GetSize () << " at time " <<
Simulator::Now ().GetSeconds () << " from address: " <<
address.GetIpv4 () << std::endl;
char buf[2000];
memcpy(buf, packet->PeekData (), packet->GetSize ());
for (uint32_t i=0; i < packet->GetSize (); i++)
{
std::cout << buf[i];
if (i && i % 60 == 0)
std::cout << std::endl;
}
std::cout << std::endl << std::endl;
}
}
#endif
}
void CloseConnection (Ptr<Socket> localSocket)
{
//localSocket->Close ();
}
void StartFlow(Ptr<Socket> localSocket, uint32_t nBytes,
uint16_t servPort)
{
// NS_LOG_LOGIC("Starting flow at time " << Simulator::Now ().GetSeconds ());
localSocket->Connect (InetSocketAddress ("10.1.2.2", servPort));//connect
localSocket->SetConnectCallback (MakeCallback (&CloseConnection),
Callback<void, Ptr<Socket> > (),
Callback<void, Ptr<Socket> > ());
//we want to close as soon as the connection is established
//the tcp state machine and outgoing buffer will assure that
//all of the data is delivered
// Perform series of 1040 byte writes (this is a multiple of 26 since
// we want to detect data splicing in the output stream)
uint32_t writeSize = 1040;
uint8_t data[writeSize];
while (nBytes > 0) {
uint32_t curSize= nBytes > writeSize ? writeSize : nBytes;
for(uint32_t i = 0; i < curSize; ++i)
{
char m = toascii (97 + i % 26);
data[i] = m;
}
localSocket->Send (data, curSize);
nBytes -= curSize;
}
}
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
// LogComponentEnable("TcpL4Protocol", LOG_LEVEL_ALL);
// LogComponentEnable("TcpSocket", LOG_LEVEL_ALL);
// LogComponentEnable("PacketSink", LOG_LEVEL_ALL);
//LogComponentEnable("TcpLargeTransferErrors", LOG_LEVEL_ALL);
// 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 three 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> ();
// We create the channels first without any IP addressing information
Ptr<PointToPointChannel> channel0 =
PointToPointTopology::AddPointToPointLink (
n0, n1, DataRate(10000000), MilliSeconds(10));
// Later, we add IP addresses.
PointToPointTopology::AddIpv4Addresses (
channel0, n0, Ipv4Address("10.1.3.1"),
n1, Ipv4Address("10.1.3.2"));
Ptr<PointToPointChannel> channel1 =
PointToPointTopology::AddPointToPointLink (
n1, n2, DataRate(10000000), MilliSeconds(10));
PointToPointTopology::AddIpv4Addresses (
channel1, n1, Ipv4Address("10.1.2.1"),
n2, Ipv4Address("10.1.2.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, n1, channel0);
PointToPointTopology::AddIpv4Routes(n1, n2, channel1);
Ptr<Ipv4> ipv4;
ipv4 = n0->GetObject<Ipv4> ();
ipv4->SetDefaultRoute (Ipv4Address ("10.1.3.2"), 1);
ipv4 = n2->GetObject<Ipv4> ();
ipv4->SetDefaultRoute (Ipv4Address ("10.1.2.1"), 1);
///////////////////////////////////////////////////////////////////////////
// Simulation 1
//
// Send 2000000 bytes over a connection to server port 50000 at time 0
// Should observe SYN exchange, a lot of data segments, and FIN exchange
//
///////////////////////////////////////////////////////////////////////////
int nBytes = 2000000;
uint16_t servPort = 50000;
Ptr<SocketFactory> socketFactory =
n0->GetObject<SocketFactory> ();
Ptr<Socket> localSocket = socketFactory->CreateSocket ();
localSocket->Bind ();
// Create a packet sink to receive these packets
Ptr<PacketSink> sink = Create<PacketSink> (
n2,
InetSocketAddress (Ipv4Address::GetAny (), servPort),
"Tcp");
sink->Start (Seconds (0.0));
sink->Stop (Seconds (10000.0));
//
// Error models
//
// We want to add an error model to node 2's NetDevice
// We can obtain a handle to the NetDevice via the channel and node
// pointers
Ptr<PointToPointNetDevice> nd2 = PointToPointTopology::GetNetDevice
(n2, channel1);
Ptr<RateErrorModel> rem = Create<RateErrorModel> ();
// The first data segment for this flow is packet uid=4
rem->SetRandomVariable (UniformVariable ());
rem->SetUnit (EU_PKT);
rem->SetRate (0.05);
nd2->AddReceiveErrorModel (rem);
Simulator::Schedule(Seconds(0), &StartFlow, localSocket, nBytes,
servPort);
// Configure tracing of all enqueue, dequeue, and NetDevice receive events
// Trace output will be sent to the simple-examples.tr file
AsciiTrace asciitrace ("tcp-large-transfer-errors.tr");
asciitrace.TraceAllQueues ();
asciitrace.TraceAllNetDeviceRx ();
// Also configure some tcpdump traces; each interface will be traced
// The output files will be named
// simple-examples.pcap-<nodeId>-<interfaceId>
// and can be read by the "tcpdump -r" command (use "-tt" option to
// display timestamps correctly)
PcapTrace pcaptrace ("tcp-large-transfer-errors.pcap");
pcaptrace.TraceAllIp ();
NodeList::Connect ("/nodes/*/applications/*/rx", MakeCallback (&ApplicationTraceSink));
Simulator::StopAt (Seconds(10000));
Simulator::Run ();
Simulator::Destroy ();
}
+229
View File
@@ -0,0 +1,229 @@
/* -*- 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
*
*/
//
// Network topology
//
// 10Mb/s, 10ms 10Mb/s, 10ms
// n0-----------------n1-----------------n2
//
//
// - Tracing of queues and packet receptions to file
// "tcp-large-transfer.tr"
// - pcap traces also generated in the following files
// "tcp-large-transfer.pcap-$n-$i" where n and i represent node and interface numbers respectively
// Usage (e.g.): ./waf --run tcp-large-transfer
#include <ctype.h>
#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/log.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/point-to-point-channel.h"
#include "ns3/point-to-point-net-device.h"
#include "ns3/ipv4-address.h"
#include "ns3/inet-socket-address.h"
#include "ns3/ipv4.h"
#include "ns3/socket.h"
#include "ns3/ipv4-route.h"
#include "ns3/point-to-point-topology.h"
#include "ns3/onoff-application.h"
#include "ns3/packet-sink.h"
#include "ns3/error-model.h"
#include "ns3/node-list.h"
#include "ns3/tcp.h"
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("TcpLargeTransfer");
void
ApplicationTraceSink (const TraceContext &context, Ptr<const Packet> packet,
const Address &addr)
{
// g_log is not declared in optimized builds
// should convert this to use of some other flag than the logging system
#ifdef NS3_LOG_ENABLE
if (!g_log.IsNoneEnabled ()) {
if (InetSocketAddress::IsMatchingType (addr) )
{
InetSocketAddress address = InetSocketAddress::ConvertFrom (addr);
std::cout << "PacketSink received size " <<
packet->GetSize () << " at time " <<
Simulator::Now ().GetSeconds () << " from address: " <<
address.GetIpv4 () << std::endl;
char buf[2000];
memcpy(buf, packet->PeekData (), packet->GetSize ());
for (uint32_t i=0; i < packet->GetSize (); i++)
{
std::cout << buf[i];
if (i && i % 60 == 0)
std::cout << std::endl;
}
std::cout << std::endl << std::endl;
}
}
#endif
}
void CloseConnection (Ptr<Socket> localSocket)
{
//localSocket->Close ();
}
void StartFlow(Ptr<Socket> localSocket, uint32_t nBytes,
uint16_t servPort)
{
// NS_LOG_LOGIC("Starting flow at time " << Simulator::Now ().GetSeconds ());
localSocket->Connect (InetSocketAddress ("10.1.2.2", servPort));//connect
localSocket->SetConnectCallback (MakeCallback (&CloseConnection),
Callback<void, Ptr<Socket> > (),
Callback<void, Ptr<Socket> > ());
//we want to close as soon as the connection is established
//the tcp state machine and outgoing buffer will assure that
//all of the data is delivered
// Perform series of 1040 byte writes (this is a multiple of 26 since
// we want to detect data splicing in the output stream)
uint32_t writeSize = 1040;
uint8_t data[writeSize];
while (nBytes > 0) {
uint32_t curSize= nBytes > writeSize ? writeSize : nBytes;
for(uint32_t i = 0; i < curSize; ++i)
{
char m = toascii (97 + i % 26);
data[i] = m;
}
localSocket->Send (data, curSize);
nBytes -= curSize;
}
}
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
// LogComponentEnable("TcpL4Protocol", LOG_LEVEL_ALL);
// LogComponentEnable("TcpSocket", LOG_LEVEL_ALL);
// LogComponentEnable("PacketSink", LOG_LEVEL_ALL);
//LogComponentEnable("TcpLargeTransfer", LOG_LEVEL_ALL);
// 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 three 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> ();
// We create the channels first without any IP addressing information
Ptr<PointToPointChannel> channel0 =
PointToPointTopology::AddPointToPointLink (
n0, n1, DataRate(10000000), MilliSeconds(10));
// Later, we add IP addresses.
PointToPointTopology::AddIpv4Addresses (
channel0, n0, Ipv4Address("10.1.3.1"),
n1, Ipv4Address("10.1.3.2"));
Ptr<PointToPointChannel> channel1 =
PointToPointTopology::AddPointToPointLink (
n1, n2, DataRate(10000000), MilliSeconds(10));
PointToPointTopology::AddIpv4Addresses (
channel1, n1, Ipv4Address("10.1.2.1"),
n2, Ipv4Address("10.1.2.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, n1, channel0);
PointToPointTopology::AddIpv4Routes(n1, n2, channel1);
Ptr<Ipv4> ipv4;
ipv4 = n0->GetObject<Ipv4> ();
ipv4->SetDefaultRoute (Ipv4Address ("10.1.3.2"), 1);
ipv4 = n2->GetObject<Ipv4> ();
ipv4->SetDefaultRoute (Ipv4Address ("10.1.2.1"), 1);
///////////////////////////////////////////////////////////////////////////
// Simulation 1
//
// Send 2000000 bytes over a connection to server port 50000 at time 0
// Should observe SYN exchange, a lot of data segments, and FIN exchange
//
///////////////////////////////////////////////////////////////////////////
int nBytes = 2000000;
uint16_t servPort = 50000;
Ptr<SocketFactory> socketFactory =
n0->GetObject<SocketFactory> ();
Ptr<Socket> localSocket = socketFactory->CreateSocket ();
localSocket->Bind ();
// Create a packet sink to receive these packets
Ptr<PacketSink> sink = Create<PacketSink> (
n2,
InetSocketAddress (Ipv4Address::GetAny (), servPort),
"Tcp");
sink->Start (Seconds (0.0));
sink->Stop (Seconds (100.0));
Simulator::Schedule(Seconds(0), &StartFlow, localSocket, nBytes,
servPort);
// Configure tracing of all enqueue, dequeue, and NetDevice receive events
// Trace output will be sent to the simple-examples.tr file
AsciiTrace asciitrace ("tcp-large-transfer.tr");
asciitrace.TraceAllQueues ();
asciitrace.TraceAllNetDeviceRx ();
// Also configure some tcpdump traces; each interface will be traced
// The output files will be named
// simple-examples.pcap-<nodeId>-<interfaceId>
// and can be read by the "tcpdump -r" command (use "-tt" option to
// display timestamps correctly)
PcapTrace pcaptrace ("tcp-large-transfer.pcap");
pcaptrace.TraceAllIp ();
NodeList::Connect ("/nodes/*/applications/*/rx", MakeCallback (&ApplicationTraceSink));
Simulator::StopAt (Seconds(1000));
Simulator::Run ();
Simulator::Destroy ();
}
+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
*
*/
//
// Network topology
//
// 100Kb/s, 10ms 1Mb/s, 10ms
// n0-----------------n1-----------------n2
//
//
// - Tracing of queues and packet receptions to file
// "tcp-nonlistening-server.tr"
// - pcap traces also generated in the following files
// "tcp-nonlistening-server.pcap-$n-$i" where n and i represent node and interface numbers respectively
// Usage (e.g.): ./waf --run tcp-nonlistening-server
#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/log.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/point-to-point-channel.h"
#include "ns3/point-to-point-net-device.h"
#include "ns3/ipv4-address.h"
#include "ns3/inet-socket-address.h"
#include "ns3/ipv4.h"
#include "ns3/socket.h"
#include "ns3/ipv4-route.h"
#include "ns3/point-to-point-topology.h"
#include "ns3/onoff-application.h"
#include "ns3/packet-sink.h"
#include "ns3/error-model.h"
#include "ns3/tcp.h"
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("TcpNonListeningServer");
void ConnectionSucceededCallback (Ptr<Socket> localSocket)
{
uint32_t nBytes = 2000;
uint8_t data[nBytes];
for(uint32_t i = 0; i < nBytes; ++i)
{
char m = 'A';
data[i] = m;
} //put something interesting in the packets ABCDEF...
localSocket->Send (data, nBytes);
}
void ConnectionFailedCallback (Ptr<Socket> localSocket)
{
NS_LOG_ERROR("Connection failed at time " << Simulator::Now ().GetSeconds ());
}
void StartFlow(Ptr<Socket> localSocket, uint16_t servPort)
{
NS_LOG_LOGIC(std::endl << "Connection attempt at time " <<
Simulator::Now ().GetSeconds () << std::endl);
localSocket->Connect (InetSocketAddress ("10.1.2.2", servPort));
localSocket->SetConnectCallback (
MakeCallback (&ConnectionSucceededCallback),
MakeCallback (&ConnectionFailedCallback),
MakeNullCallback<void, Ptr<Socket> > () );
}
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
//LogComponentEnable("TcpL4Protocol", LOG_LEVEL_ALL);
//LogComponentEnable("TcpSocket", LOG_LEVEL_ALL);
LogComponentEnable("TcpNonListeningServer", LOG_LEVEL_ALL);
// 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 three 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> ();
// We create the channels first without any IP addressing information
Ptr<PointToPointChannel> channel0 =
PointToPointTopology::AddPointToPointLink (
n0, n1, DataRate(1000000), MilliSeconds(10));
// Later, we add IP addresses.
PointToPointTopology::AddIpv4Addresses (
channel0, n0, Ipv4Address("10.1.3.1"),
n1, Ipv4Address("10.1.3.2"));
Ptr<PointToPointChannel> channel1 =
PointToPointTopology::AddPointToPointLink (
n1, n2, DataRate(100000), MilliSeconds(10));
PointToPointTopology::AddIpv4Addresses (
channel1, n1, Ipv4Address("10.1.2.1"),
n2, Ipv4Address("10.1.2.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, n1, channel0);
PointToPointTopology::AddIpv4Routes(n1, n2, channel1);
Ptr<Ipv4> ipv4;
ipv4 = n0->GetObject<Ipv4> ();
ipv4->SetDefaultRoute (Ipv4Address ("10.1.3.2"), 1);
ipv4 = n2->GetObject<Ipv4> ();
ipv4->SetDefaultRoute (Ipv4Address ("10.1.2.1"), 1);
///////////////////////////////////////////////////////////////////////////
// Simulation 1
//
// Send 2000 bytes over a connection to server port 500 at time 0
// Should observe SYN exchange, two data segments, and FIN exchange
//
///////////////////////////////////////////////////////////////////////////
uint16_t servPort = 500;
Ptr<SocketFactory> socketFactory =
n0->GetObject<SocketFactory> ();
Ptr<Socket> localSocket = socketFactory->CreateSocket ();
localSocket->Bind ();
#ifdef NOTFORTHISSCRIPT
// Create an optional packet sink to receive these packets
Ptr<PacketSink> sink = Create<PacketSink> (
n2,
InetSocketAddress (Ipv4Address::GetAny (), servPort),
"Tcp");
// Start the sink
sink->Start (Seconds (0.0));
sink->Stop (Seconds (10.0));
#endif
Simulator::Schedule(Seconds(0), &StartFlow, localSocket, servPort);
// Configure tracing of all enqueue, dequeue, and NetDevice receive events
// Trace output will be sent to the simple-examples.tr file
AsciiTrace asciitrace ("tcp-nonlistening-server.tr");
asciitrace.TraceAllQueues ();
asciitrace.TraceAllNetDeviceRx ();
// Also configure some tcpdump traces; each interface will be traced
// The output files will be named
// simple-examples.pcap-<nodeId>-<interfaceId>
// and can be read by the "tcpdump -r" command (use "-tt" option to
// display timestamps correctly)
PcapTrace pcaptrace ("tcp-nonlistening-server.pcap");
pcaptrace.TraceAllIp ();
Simulator::StopAt (Seconds(1000));
Simulator::Run ();
Simulator::Destroy ();
}
+226
View File
@@ -0,0 +1,226 @@
/* -*- 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
*
*/
//
// Network topology
//
// 100Kb/s, 10ms 1Mb/s, 10ms
// n0-----------------n1-----------------n2
//
//
// - Tracing of queues and packet receptions to file
// "tcp-small-transfer-oneloss.tr"
// - pcap traces also generated in the following files
// "tcp-small-transfer-oneloss.pcap-$n-$i" where n and i represent node and interface numbers respectively
// Usage (e.g.): ./waf --run tcp-small-transfer-oneloss
#include <ctype.h>
#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/log.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/point-to-point-channel.h"
#include "ns3/point-to-point-net-device.h"
#include "ns3/ipv4-address.h"
#include "ns3/inet-socket-address.h"
#include "ns3/ipv4.h"
#include "ns3/socket.h"
#include "ns3/ipv4-route.h"
#include "ns3/point-to-point-topology.h"
#include "ns3/onoff-application.h"
#include "ns3/packet-sink.h"
#include "ns3/error-model.h"
#include "ns3/node-list.h"
#include "ns3/tcp.h"
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("TcpSmallTransferOneloss");
void
ApplicationTraceSink (const TraceContext &context, Ptr<const Packet> packet,
const Address &addr)
{
// g_log is not declared in optimized builds
// should convert this to use of some other flag than the logging system
#ifdef NS3_LOG_ENABLE
if (!g_log.IsNoneEnabled ()) {
if (InetSocketAddress::IsMatchingType (addr) )
{
InetSocketAddress address = InetSocketAddress::ConvertFrom (addr);
std::cout << "PacketSink received size " <<
packet->GetSize () << " at time " <<
Simulator::Now ().GetSeconds () << " from address: " <<
address.GetIpv4 () << std::endl;
char buf[2000];
memcpy(buf, packet->PeekData (), packet->GetSize ());
for (uint32_t i=0; i < packet->GetSize (); i++)
{
std::cout << buf[i];
if (i && i % 60 == 0)
std::cout << std::endl;
}
std::cout << std::endl << std::endl;
}
}
#endif
}
void StartFlow(Ptr<Socket> localSocket, uint32_t nBytes,
uint16_t servPort)
{
// NS_LOG_LOGIC("Starting flow at time " << Simulator::Now ().GetSeconds ());
localSocket->Connect (InetSocketAddress ("10.1.2.2", servPort));
uint8_t data[nBytes];
for(uint32_t i = 0; i < nBytes; ++i)
{
char m = toascii (97 + i % 26);
data[i] = m;
}
localSocket->Send (data, nBytes);
}
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
// LogComponentEnable("TcpL4Protocol", LOG_LEVEL_ALL);
// LogComponentEnable("TcpSocket", LOG_LEVEL_ALL);
// LogComponentEnable("PacketSink", LOG_LEVEL_ALL);
LogComponentEnable("TcpSmallTransferOneloss", LOG_LEVEL_ALL);
// 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 three 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> ();
// We create the channels first without any IP addressing information
Ptr<PointToPointChannel> channel0 =
PointToPointTopology::AddPointToPointLink (
n0, n1, DataRate(1000000), MilliSeconds(10));
// Later, we add IP addresses.
PointToPointTopology::AddIpv4Addresses (
channel0, n0, Ipv4Address("10.1.3.1"),
n1, Ipv4Address("10.1.3.2"));
Ptr<PointToPointChannel> channel1 =
PointToPointTopology::AddPointToPointLink (
n1, n2, DataRate(100000), MilliSeconds(10));
PointToPointTopology::AddIpv4Addresses (
channel1, n1, Ipv4Address("10.1.2.1"),
n2, Ipv4Address("10.1.2.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, n1, channel0);
PointToPointTopology::AddIpv4Routes(n1, n2, channel1);
Ptr<Ipv4> ipv4;
ipv4 = n0->GetObject<Ipv4> ();
ipv4->SetDefaultRoute (Ipv4Address ("10.1.3.2"), 1);
ipv4 = n2->GetObject<Ipv4> ();
ipv4->SetDefaultRoute (Ipv4Address ("10.1.2.1"), 1);
///////////////////////////////////////////////////////////////////////////
// Simulation 1
//
// Send 2000 bytes over a connection to server port 500 at time 0
// Should observe SYN exchange, two data segments, and FIN exchange
// Force the loss of the first data segment
//
///////////////////////////////////////////////////////////////////////////
int nBytes = 2000;
uint16_t servPort = 500;
Ptr<SocketFactory> socketFactory =
n0->GetObject<SocketFactory> ();
Ptr<Socket> localSocket = socketFactory->CreateSocket ();
localSocket->Bind ();
// Create a packet sink to receive these packets
Ptr<PacketSink> sink = Create<PacketSink> (
n2,
InetSocketAddress (Ipv4Address::GetAny (), servPort),
"Tcp");
sink->Start (Seconds (0.0));
sink->Stop (Seconds (100.0));
//
// Error models
//
// We want to add an error model to node 2's NetDevice
// We can obtain a handle to the NetDevice via the channel and node
// pointers
Ptr<PointToPointNetDevice> nd2 = PointToPointTopology::GetNetDevice
(n2, channel1);
Ptr<ListErrorModel> pem = Create<ListErrorModel> ();
std::list<uint32_t> sampleList;
// The first data segment for this flow is packet uid=4
sampleList.push_back (4);
pem->SetList (sampleList);
nd2->AddReceiveErrorModel (pem);
Simulator::Schedule(Seconds(0), &StartFlow, localSocket, nBytes,
servPort);
// Configure tracing of all enqueue, dequeue, and NetDevice receive events
// Trace output will be sent to the simple-examples.tr file
AsciiTrace asciitrace ("tcp-small-transfer-oneloss.tr");
asciitrace.TraceAllQueues ();
asciitrace.TraceAllNetDeviceRx ();
// Also configure some tcpdump traces; each interface will be traced
// The output files will be named
// simple-examples.pcap-<nodeId>-<interfaceId>
// and can be read by the "tcpdump -r" command (use "-tt" option to
// display timestamps correctly)
PcapTrace pcaptrace ("tcp-small-transfer-oneloss.pcap");
pcaptrace.TraceAllIp ();
NodeList::Connect ("/nodes/*/applications/*/rx", MakeCallback (&ApplicationTraceSink));
Simulator::StopAt (Seconds(1000));
Simulator::Run ();
Simulator::Destroy ();
}
+221
View File
@@ -0,0 +1,221 @@
/* -*- 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
*
*/
//
// Network topology
//
// 100Kb/s, 10ms 1Mb/s, 10ms
// n0-----------------n1-----------------n2
//
//
// - Tracing of queues and packet receptions to file
// "tcp-small-transfer.tr"
// - pcap traces also generated in the following files
// "tcp-small-transfer.pcap-$n-$i" where n and i represent node and interface numbers respectively
// Usage (e.g.): ./waf --run tcp-small-transfer
#include <ctype.h>
#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/log.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/point-to-point-channel.h"
#include "ns3/point-to-point-net-device.h"
#include "ns3/ipv4-address.h"
#include "ns3/inet-socket-address.h"
#include "ns3/ipv4.h"
#include "ns3/socket.h"
#include "ns3/ipv4-route.h"
#include "ns3/point-to-point-topology.h"
#include "ns3/onoff-application.h"
#include "ns3/packet-sink.h"
#include "ns3/error-model.h"
#include "ns3/node-list.h"
#include "ns3/tcp.h"
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("TcpSmallTransfer");
void
ApplicationTraceSink (const TraceContext &context, Ptr<const Packet> packet,
const Address &addr)
{
// g_log is not declared in optimized builds
// should convert this to use of some other flag than the logging system
#ifdef NS3_LOG_ENABLE
if (!g_log.IsNoneEnabled ()) {
if (InetSocketAddress::IsMatchingType (addr) )
{
InetSocketAddress address = InetSocketAddress::ConvertFrom (addr);
std::cout << "PacketSink received size " <<
packet->GetSize () << " at time " <<
Simulator::Now ().GetSeconds () << " from address: " <<
address.GetIpv4 () << std::endl;
char buf[2000];
memcpy(buf, packet->PeekData (), packet->GetSize ());
for (uint32_t i=0; i < packet->GetSize (); i++)
{
std::cout << buf[i];
if (i && i % 60 == 0)
std::cout << std::endl;
}
std::cout << std::endl << std::endl;
}
}
#endif
}
void CloseConnection (Ptr<Socket> localSocket)
{
localSocket->Close ();
}
void StartFlow(Ptr<Socket> localSocket, uint32_t nBytes,
uint16_t servPort)
{
// NS_LOG_LOGIC("Starting flow at time " << Simulator::Now ().GetSeconds ());
localSocket->Connect (InetSocketAddress ("10.1.2.2", servPort));//connect
localSocket->SetConnectCallback (MakeCallback (&CloseConnection),
MakeNullCallback<void, Ptr<Socket> > (),
MakeNullCallback<void, Ptr<Socket> > ());
//we want to close as soon as the connection is established
//the tcp state machine and outgoing buffer will assure that
//all of the data is delivered
uint8_t data[nBytes];
for(uint32_t i = 0; i < nBytes; ++i)
{
char m = toascii (97 + i % 26);
data[i] = m;
}
localSocket->Send (data, nBytes);
}
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
// LogComponentEnable("TcpL4Protocol", LOG_LEVEL_ALL);
// LogComponentEnable("TcpSocket", LOG_LEVEL_ALL);
// LogComponentEnable("PacketSink", LOG_LEVEL_ALL);
LogComponentEnable("TcpSmallTransfer", LOG_LEVEL_ALL);
// 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 three 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> ();
// We create the channels first without any IP addressing information
Ptr<PointToPointChannel> channel0 =
PointToPointTopology::AddPointToPointLink (
n0, n1, DataRate(1000000), MilliSeconds(10));
// Later, we add IP addresses.
PointToPointTopology::AddIpv4Addresses (
channel0, n0, Ipv4Address("10.1.3.1"),
n1, Ipv4Address("10.1.3.2"));
Ptr<PointToPointChannel> channel1 =
PointToPointTopology::AddPointToPointLink (
n1, n2, DataRate(100000), MilliSeconds(10));
PointToPointTopology::AddIpv4Addresses (
channel1, n1, Ipv4Address("10.1.2.1"),
n2, Ipv4Address("10.1.2.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, n1, channel0);
PointToPointTopology::AddIpv4Routes(n1, n2, channel1);
Ptr<Ipv4> ipv4;
ipv4 = n0->GetObject<Ipv4> ();
ipv4->SetDefaultRoute (Ipv4Address ("10.1.3.2"), 1);
ipv4 = n2->GetObject<Ipv4> ();
ipv4->SetDefaultRoute (Ipv4Address ("10.1.2.1"), 1);
///////////////////////////////////////////////////////////////////////////
// Simulation 1
//
// Send 2000 bytes over a connection to server port 500 at time 0
// Should observe SYN exchange, two data segments, and FIN exchange
//
///////////////////////////////////////////////////////////////////////////
int nBytes = 2000;
uint16_t servPort = 500;
Ptr<SocketFactory> socketFactory =
n0->GetObject<SocketFactory> ();
Ptr<Socket> localSocket = socketFactory->CreateSocket ();
localSocket->Bind ();
// Create a packet sink to receive these packets
Ptr<PacketSink> sink = Create<PacketSink> (
n2,
InetSocketAddress (Ipv4Address::GetAny (), servPort),
"Tcp");
sink->Start (Seconds (0.0));
sink->Stop (Seconds (100.0));
Simulator::Schedule(Seconds(0), &StartFlow, localSocket, nBytes,
servPort);
// Configure tracing of all enqueue, dequeue, and NetDevice receive events
// Trace output will be sent to the simple-examples.tr file
AsciiTrace asciitrace ("tcp-small-transfer.tr");
asciitrace.TraceAllQueues ();
asciitrace.TraceAllNetDeviceRx ();
// Also configure some tcpdump traces; each interface will be traced
// The output files will be named
// simple-examples.pcap-<nodeId>-<interfaceId>
// and can be read by the "tcpdump -r" command (use "-tt" option to
// display timestamps correctly)
PcapTrace pcaptrace ("tcp-small-transfer.pcap");
pcaptrace.TraceAllIp ();
NodeList::Connect ("/nodes/*/applications/*/rx", MakeCallback (&ApplicationTraceSink));
Simulator::StopAt (Seconds(1000));
Simulator::Run ();
Simulator::Destroy ();
}
+6 -6
View File
@@ -100,10 +100,10 @@ main (int argc, char *argv[])
// Explicitly create the nodes required by the topology (shown above).
//
NS_LOG_INFO ("Create nodes.");
Ptr<Node> n0 = Create<InternetNode> ();
Ptr<Node> n1 = Create<InternetNode> ();
Ptr<Node> n2 = Create<InternetNode> ();
Ptr<Node> n3 = Create<InternetNode> ();
Ptr<Node> n0 = CreateObject<InternetNode> ();
Ptr<Node> n1 = CreateObject<InternetNode> ();
Ptr<Node> n2 = CreateObject<InternetNode> ();
Ptr<Node> n3 = CreateObject<InternetNode> ();
NS_LOG_INFO ("Create channels.");
//
@@ -167,7 +167,7 @@ main (int argc, char *argv[])
//
uint16_t port = 9; // well-known echo port number
Ptr<UdpEchoServer> server = Create<UdpEchoServer> (n1, port);
Ptr<UdpEchoServer> server = CreateObject<UdpEchoServer> (n1, port);
//
// Create a UdpEchoClient application to send UDP datagrams from node zero to
// node one.
@@ -176,7 +176,7 @@ main (int argc, char *argv[])
uint32_t maxPacketCount = 1;
Time interPacketInterval = Seconds (1.);
Ptr<UdpEchoClient> client = Create<UdpEchoClient> (n0, "10.1.1.2", port,
Ptr<UdpEchoClient> client = CreateObject<UdpEchoClient> (n0, "10.1.1.2", port,
maxPacketCount, interPacketInterval, packetSize);
//
// Tell the applications when to start and stop.
+22
View File
@@ -45,3 +45,25 @@ def build(bld):
obj = bld.create_ns3_program('simple-point-to-point-olsr',
['point-to-point', 'internet-node', 'olsr'])
obj.source = 'simple-point-to-point-olsr.cc'
obj = bld.create_ns3_program('tcp-large-transfer',
['point-to-point', 'internet-node'])
obj.source = 'tcp-large-transfer.cc'
obj = bld.create_ns3_program('tcp-large-transfer-errors',
['point-to-point', 'internet-node'])
obj.source = 'tcp-large-transfer-errors.cc'
obj = bld.create_ns3_program('tcp-nonlistening-server',
['point-to-point', 'internet-node'])
obj.source = 'tcp-nonlistening-server.cc'
obj = bld.create_ns3_program('tcp-small-transfer',
['point-to-point', 'internet-node'])
obj.source = 'tcp-small-transfer.cc'
obj = bld.create_ns3_program('tcp-small-transfer-oneloss',
['point-to-point', 'internet-node'])
obj.source = 'tcp-small-transfer-oneloss.cc'
+251
View File
@@ -0,0 +1,251 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2005,2006,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 "ns3/wifi-net-device.h"
#include "ns3/wifi-channel.h"
#include "ns3/simulator.h"
#include "ns3/callback.h"
#include "ns3/ptr.h"
#include "ns3/node.h"
#include "ns3/onoff-application.h"
#include "ns3/static-mobility-model.h"
#include "ns3/random-variable.h"
#include "ns3/packet-socket-address.h"
#include "ns3/packet.h"
#include "ns3/socket.h"
#include "ns3/socket-factory.h"
#include "ns3/command-line.h"
#include "ns3/gnuplot.h"
#include <iostream>
using namespace ns3;
static uint32_t g_bytesTotal = 0;
static GnuplotDataset *g_output = 0;
static Ptr<Node>
CreateAdhocNode (Ptr<WifiChannel> channel,
Vector position, const char *address)
{
Ptr<Node> node = CreateObject<Node> ();
Ptr<AdhocWifiNetDevice> device = CreateObject<AdhocWifiNetDevice> (node, Mac48Address (address));
device->Attach (channel);
Ptr<MobilityModel> mobility = CreateObject<StaticMobilityModel> ();
mobility->SetPosition (position);
node->AggregateObject (mobility);
return node;
}
static void
SetPosition (Ptr<Node> node, Vector position)
{
Ptr<MobilityModel> mobility = node->GetObject<MobilityModel> ();
mobility->SetPosition (position);
}
static Vector
GetPosition (Ptr<Node> node)
{
Ptr<MobilityModel> mobility = node->GetObject<MobilityModel> ();
return mobility->GetPosition ();
}
static void
AdvancePosition (Ptr<Node> node)
{
Vector pos = GetPosition (node);
double mbs = ((g_bytesTotal * 8.0) / 1000000);
g_bytesTotal = 0;
g_output->Add (pos.x, mbs);
pos.x += 1.0;
if (pos.x >= 210.0)
{
return;
}
SetPosition (node, pos);
//std::cout << "x="<<pos.x << std::endl;
Simulator::Schedule (Seconds (1.0), &AdvancePosition, node);
}
static void
ReceivePacket (Ptr<Socket> socket, Ptr<Packet> packet, const Address &address)
{
g_bytesTotal += packet->GetSize ();
}
static Ptr<Socket>
SetupPacketReceive (Ptr<Node> node, uint16_t port)
{
TypeId tid = TypeId::LookupByName ("Packet");
Ptr<SocketFactory> socketFactory = node->GetObject<SocketFactory> (tid);
Ptr<Socket> sink = socketFactory->CreateSocket ();
sink->Bind ();
sink->SetRecvCallback (MakeCallback (&ReceivePacket));
return sink;
}
static void
RunOneExperiment (void)
{
g_bytesTotal = 0;
Ptr<WifiChannel> channel = CreateObject<WifiChannel> ();
Ptr<Node> a = CreateAdhocNode (channel,
Vector (5.0,0.0,0.0),
"00:00:00:00:00:01");
Ptr<Node> b = CreateAdhocNode (channel,
Vector (0.0, 0.0, 0.0),
"00:00:00:00:00:02");
PacketSocketAddress destination = PacketSocketAddress ();
destination.SetProtocol (1);
destination.SetSingleDevice (0);
destination.SetPhysicalAddress (Mac48Address ("00:00:00:00:00:02"));
Ptr<Application> app = CreateObject<OnOffApplication> (a, destination,
"Packet",
ConstantVariable (250),
ConstantVariable (0),
DataRate (60000000),
2000);
app->Start (Seconds (0.5));
app->Stop (Seconds (250.0));
Simulator::Schedule (Seconds (1.5), &AdvancePosition, b);
Ptr<Socket> recvSink = SetupPacketReceive (b, 10);
Simulator::Run ();
Simulator::Destroy ();
}
int main (int argc, char *argv[])
{
Simulator::SetLinkedList ();
// disable fragmentation
DefaultValue::Bind ("WifiFragmentationThreshold", "2200");
CommandLine::Parse (argc, argv);
Gnuplot gnuplot = Gnuplot ("reference-rates.png");
DefaultValue::Bind ("WifiRtsCtsThreshold", "2200");
g_output = new GnuplotDataset ("54mb");
g_output->SetStyle (GnuplotDataset::LINES);
DefaultValue::Bind ("WifiRateControlAlgorithm", "ConstantRate");
DefaultValue::Bind ("WifiConstantDataRate", "54mb");
RunOneExperiment ();
gnuplot.AddDataset (*g_output);
delete g_output;
g_output = new GnuplotDataset ("48mb");
g_output->SetStyle (GnuplotDataset::LINES);
DefaultValue::Bind ("WifiRateControlAlgorithm", "ConstantRate");
DefaultValue::Bind ("WifiConstantDataRate", "48mb");
RunOneExperiment ();
gnuplot.AddDataset (*g_output);
delete g_output;
g_output = new GnuplotDataset ("36mb");
g_output->SetStyle (GnuplotDataset::LINES);
DefaultValue::Bind ("WifiRateControlAlgorithm", "ConstantRate");
DefaultValue::Bind ("WifiConstantDataRate", "36mb");
RunOneExperiment ();
gnuplot.AddDataset (*g_output);
delete g_output;
g_output = new GnuplotDataset ("24mb");
g_output->SetStyle (GnuplotDataset::LINES);
DefaultValue::Bind ("WifiRateControlAlgorithm", "ConstantRate");
DefaultValue::Bind ("WifiConstantDataRate", "24mb");
RunOneExperiment ();
gnuplot.AddDataset (*g_output);
delete g_output;
g_output = new GnuplotDataset ("18mb");
g_output->SetStyle (GnuplotDataset::LINES);
DefaultValue::Bind ("WifiRateControlAlgorithm", "ConstantRate");
DefaultValue::Bind ("WifiConstantDataRate", "18mb");
RunOneExperiment ();
gnuplot.AddDataset (*g_output);
delete g_output;
g_output = new GnuplotDataset ("12mb");
g_output->SetStyle (GnuplotDataset::LINES);
DefaultValue::Bind ("WifiRateControlAlgorithm", "ConstantRate");
DefaultValue::Bind ("WifiConstantDataRate", "12mb");
RunOneExperiment ();
gnuplot.AddDataset (*g_output);
delete g_output;
g_output = new GnuplotDataset ("9mb");
g_output->SetStyle (GnuplotDataset::LINES);
DefaultValue::Bind ("WifiRateControlAlgorithm", "ConstantRate");
DefaultValue::Bind ("WifiConstantDataRate", "9mb");
RunOneExperiment ();
gnuplot.AddDataset (*g_output);
delete g_output;
g_output = new GnuplotDataset ("6mb");
g_output->SetStyle (GnuplotDataset::LINES);
DefaultValue::Bind ("WifiRateControlAlgorithm", "ConstantRate");
DefaultValue::Bind ("WifiConstantDataRate", "6mb");
RunOneExperiment ();
gnuplot.AddDataset (*g_output);
delete g_output;
gnuplot.GenerateOutput (std::cout);
gnuplot = Gnuplot ("rate-control.png");
DefaultValue::Bind ("WifiPhyStandard", "holland");
g_output = new GnuplotDataset ("arf");
g_output->SetStyle (GnuplotDataset::LINES);
DefaultValue::Bind ("WifiRtsCtsThreshold", "2200");
DefaultValue::Bind ("WifiRateControlAlgorithm", "Arf");
RunOneExperiment ();
gnuplot.AddDataset (*g_output);
delete g_output;
g_output = new GnuplotDataset ("aarf");
g_output->SetStyle (GnuplotDataset::LINES);
DefaultValue::Bind ("WifiRtsCtsThreshold", "2200");
DefaultValue::Bind ("WifiRateControlAlgorithm", "Aarf");
RunOneExperiment ();
gnuplot.AddDataset (*g_output);
delete g_output;
g_output = new GnuplotDataset ("ideal");
g_output->SetStyle (GnuplotDataset::LINES);
DefaultValue::Bind ("WifiRtsCtsThreshold", "2200");
DefaultValue::Bind ("WifiRateControlAlgorithm", "Ideal");
RunOneExperiment ();
gnuplot.AddDataset (*g_output);
delete g_output;
gnuplot.GenerateOutput (std::cout);
return 0;
}
+188
View File
@@ -0,0 +1,188 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2005,2006,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 "ns3/wifi-net-device.h"
#include "ns3/wifi-channel.h"
#include "ns3/wifi-phy.h"
#include "ns3/simulator.h"
#include "ns3/callback.h"
#include "ns3/ptr.h"
#include "ns3/node.h"
#include "ns3/onoff-application.h"
#include "ns3/static-mobility-model.h"
#include "ns3/random-variable.h"
#include "ns3/packet-socket-address.h"
#include "ns3/packet.h"
#include "ns3/node-list.h"
#include <iostream>
using namespace ns3;
void
WifiNetDeviceTrace (const TraceContext &context, Ptr<const Packet> p, Mac48Address address)
{
std::cout << context << " ad=" << address << " p: " << p << std::endl;
}
void
WifiPhyStateTrace (const TraceContext &context, Time start, Time duration, enum WifiPhy::State state)
{
std::cout << context << " state=";
switch (state) {
case WifiPhy::TX:
std::cout << "tx ";
break;
case WifiPhy::SYNC:
std::cout << "sync ";
break;
case WifiPhy::CCA_BUSY:
std::cout << "cca-busy";
break;
case WifiPhy::IDLE:
std::cout << "idle ";
break;
}
std::cout << " start="<<start<<" duration="<<duration<<std::endl;
}
static Ptr<Node>
CreateApNode (Ptr<WifiChannel> channel,
Vector position,
const char *macAddress,
Ssid ssid,
Time at)
{
Ptr<Node> node = CreateObject<Node> ();
Ptr<NqapWifiNetDevice> device = CreateObject<NqapWifiNetDevice> (node, Mac48Address (macAddress));
device->SetSsid (ssid);
Simulator::Schedule (at, &NqapWifiNetDevice::StartBeaconing, device);
device->Attach (channel);
Ptr<MobilityModel> mobility = CreateObject<StaticMobilityModel> ();
mobility->SetPosition (position);
node->AggregateObject (mobility);
return node;
}
static Ptr<Node>
CreateStaNode (Ptr<WifiChannel> channel,
Vector position,
const char *macAddress,
Ssid ssid)
{
Ptr<Node> node = CreateObject<Node> ();
Ptr<NqstaWifiNetDevice> device = CreateObject<NqstaWifiNetDevice> (node, Mac48Address (macAddress));
Simulator::ScheduleNow (&NqstaWifiNetDevice::StartActiveAssociation, device,
ssid);
device->Attach (channel);
Ptr<MobilityModel> mobility = CreateObject<StaticMobilityModel> ();
mobility->SetPosition (position);
node->AggregateObject (mobility);
return node;
}
static void
SetPosition (Ptr<Node> node, Vector position)
{
Ptr<MobilityModel> mobility = node->GetObject<MobilityModel> ();
mobility->SetPosition (position);
}
static Vector
GetPosition (Ptr<Node> node)
{
Ptr<MobilityModel> mobility = node->GetObject<MobilityModel> ();
return mobility->GetPosition ();
}
static void
AdvancePosition (Ptr<Node> node)
{
Vector pos = GetPosition (node);
pos.x += 5.0;
if (pos.x >= 210.0)
{
return;
}
SetPosition (node, pos);
//std::cout << "x="<<pos.x << std::endl;
Simulator::Schedule (Seconds (1.0), &AdvancePosition, node);
}
int main (int argc, char *argv[])
{
Simulator::SetLinkedList ();
Packet::EnableMetadata ();
//Simulator::EnableLogTo ("80211.log");
// enable rts cts all the time.
DefaultValue::Bind ("WifiRtsCtsThreshold", "0");
// disable fragmentation
DefaultValue::Bind ("WifiFragmentationThreshold", "2200");
DefaultValue::Bind ("WifiRateControlAlgorithm", "Aarf");
//DefaultValue::Bind ("WifiRateControlAlgorithm", "Arf");
Ptr<WifiChannel> channel = CreateObject<WifiChannel> ();
Ssid ssid = Ssid ("mathieu");
Ptr<Node> a = CreateApNode (channel,
Vector (5.0,0.0,0.0),
"00:00:00:00:00:01",
ssid,
Seconds (0.1));
Simulator::Schedule (Seconds (1.0), &AdvancePosition, a);
Ptr<Node> b = CreateStaNode (channel,
Vector (0.0, 0.0, 0.0),
"00:00:00:00:00:02",
ssid);
Ptr<Node> c = CreateStaNode (channel,
Vector (0.0, 0.0, 0.0),
"00:00:00:00:00:03",
ssid);
PacketSocketAddress destination = PacketSocketAddress ();
destination.SetProtocol (1);
destination.SetSingleDevice (0);
destination.SetPhysicalAddress (Mac48Address ("00:00:00:00:00:03"));
Ptr<Application> app = CreateObject<OnOffApplication> (b, destination,
"Packet",
ConstantVariable (42),
ConstantVariable (0));
app->Start (Seconds (0.5));
app->Stop (Seconds (43.0));
//NodeList::Connect ("/nodes/*/devices/*/*", MakeCallback (&WifiNetDeviceTrace));
//NodeList::Connect ("/nodes/*/devices/*/phy/state", MakeCallback (&WifiPhyStateTrace));
Simulator::Run ();
Simulator::Destroy ();
return 0;
}
-217
View File
@@ -1,217 +0,0 @@
/* -*- 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/log.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;
NS_LOG_COMPONENT_DEFINE ("ChannelSample");
// ===========================================================================
// 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_LOG_FUNCTION;
}
FakeInternetNode::~FakeInternetNode ()
{
NS_LOG_FUNCTION;
}
void
FakeInternetNode::Doit (void)
{
NS_LOG_FUNCTION;
NS_LOG_INFO ("**** Send outbound packet");
Packet p;
m_dtqOutbound.Enqueue(p);
UpperNotify();
}
bool
FakeInternetNode::UpperDoSendUp (Packet &p)
{
NS_LOG_FUNCTION;
NS_LOG_PARAMS (this << &p);
NS_LOG_INFO ("**** Receive inbound packet");
m_dtqInbound.Enqueue(p);
return m_dtqInbound.Dequeue(p);
}
bool
FakeInternetNode::UpperDoPull (Packet &p)
{
NS_LOG_FUNCTION;
NS_LOG_PARAMS (this << &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_LOG_FUNCTION;
}
FakePhysicalLayer::~FakePhysicalLayer ()
{
NS_LOG_FUNCTION;
}
bool
FakePhysicalLayer::LowerDoNotify (LayerConnectorUpper *upper)
{
NS_LOG_FUNCTION;
Packet p;
NS_LOG_LOGIC ("Starting pull");
NS_ASSERT(m_upperPartner);
m_upperPartner->UpperPull(p);
m_dtqOutbound.Enqueue(p);
NS_LOG_LOGIC ("Got bits, Notify lower");
NS_ASSERT(m_lowerPartner);
return m_lowerPartner->LowerNotify(this);
}
bool
FakePhysicalLayer::UpperDoSendUp (Packet &p)
{
NS_LOG_FUNCTION;
NS_LOG_PARAMS (this << &p);
NS_ASSERT(m_upperPartner);
return m_upperPartner->UpperSendUp(p);
}
bool
FakePhysicalLayer::UpperDoPull (Packet &p)
{
NS_LOG_FUNCTION;
NS_LOG_PARAMS (this << &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_LOG_FUNCTION;
}
FakeChannel::~FakeChannel ()
{
NS_LOG_FUNCTION;
}
int main (int argc, char *argv[])
{
NS_LOG_INFO ("Channel Hackorama");
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
@@ -1,38 +0,0 @@
#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;
}
+3 -3
View File
@@ -17,7 +17,7 @@ int main (int argc, char *argv[])
// create an array of empty nodes for testing purposes
for (uint32_t i = 0; i < 120; i++)
{
nodes.push_back (Create<InternetNode> ());
nodes.push_back (CreateObject<InternetNode> ());
}
// setup the grid itself: objects are layed out
@@ -27,7 +27,7 @@ int main (int argc, char *argv[])
GridTopology grid (-100, -100, 20, 5, 20);
// each object will be attached a static position.
grid.SetMobilityModel (StaticMobilityModel::cid);
grid.SetMobilityModel (StaticMobilityModel::GetTypeId ());
// finalize the setup by attaching to each object
// in the input array a position and initializing
@@ -39,7 +39,7 @@ int main (int argc, char *argv[])
j != nodes.end (); j++)
{
Ptr<Object> object = *j;
Ptr<MobilityModel> position = object->QueryInterface<MobilityModel> (MobilityModel::iid);
Ptr<MobilityModel> position = object->GetObject<MobilityModel> ();
NS_ASSERT (position != 0);
Vector pos = position->GetPosition ();
std::cout << "x=" << pos.x << ", y=" << pos.y << ", z=" << pos.z << std::endl;
-121
View File
@@ -1,121 +0,0 @@
#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;
}
+6 -4
View File
@@ -1,4 +1,5 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
#include "ns3/ptr.h"
#include "ns3/packet.h"
#include "ns3/header.h"
#include <iostream>
@@ -105,16 +106,17 @@ int main (int argc, char *argv[])
sourceHeader.SetData (2);
// instantiate a packet
Packet p;
Ptr<Packet> p = Create<Packet> ();
// and store my header into the packet.
p.AddHeader (sourceHeader);
p->AddHeader (sourceHeader);
// print the content of my packet on the standard output.
p.Print (std::cout);
p->Print (std::cout);
// you can now remove the header from the packet:
MyHeader destinationHeader;
p.RemoveHeader (destinationHeader);
p->RemoveHeader (destinationHeader);
// and check that the destination and source
// headers contain the same values.
+30 -30
View File
@@ -49,7 +49,7 @@ void DefaultPrint (void)
{
// We create a packet with 1000 bytes of zero payload
// and add 3 headers to this packet.
Packet p (1000);
Ptr<Packet> p = Create<Packet> (1000);
Ipv4Header ipv4;
UdpHeader udp;
ipv4.SetSource (Ipv4Address ("192.168.0.1"));
@@ -57,36 +57,36 @@ void DefaultPrint (void)
udp.SetSource (1025);
udp.SetDestination (80);
udp.SetPayloadSize (1000);
p.AddHeader (udp);
p.AddHeader (ipv4);
p->AddHeader (udp);
p->AddHeader (ipv4);
std::cout << "full packet size=" << p.GetSize () << std::endl;
std::cout << "full packet size=" << p->GetSize () << std::endl;
// Here, invoke the default Print routine, directed to std out
p.Print (std::cout);
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);
Ptr<Packet> p1 = p->CreateFragment (0, 2);
Ptr<Packet> p2 = p->CreateFragment (2, 1000);
Ptr<Packet> p3 = p->CreateFragment (1002, 26);
std::cout << "fragment1" << std::endl;
p1.Print (std::cout);
p1->Print (std::cout);
std::cout << std::endl;
std::cout << "fragment2" << std::endl;
p2.Print (std::cout);
p2->Print (std::cout);
std::cout << std::endl;
std::cout << "fragment3" << std::endl;
p3.Print (std::cout);
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);
Ptr<Packet> aggregate = p1->Copy ();
aggregate->AddAtEnd (p2);
aggregate->AddAtEnd (p3);
std::cout << "aggregated" << std::endl;
aggregate.Print (std::cout);
aggregate->Print (std::cout);
std::cout << std::endl;
}
@@ -128,7 +128,7 @@ void NonDefaultPrint (void)
// We create a packet with 1000 bytes of zero payload
Packet p (1000);
Ptr<Packet> p = Create<Packet> (1000);
Ipv4Header ipv4;
UdpHeader udp;
ipv4.SetSource (Ipv4Address ("192.168.0.1"));
@@ -136,35 +136,35 @@ void NonDefaultPrint (void)
udp.SetSource (1025);
udp.SetDestination (80);
udp.SetPayloadSize (1000);
p.AddHeader (udp);
p.AddHeader (ipv4);
p->AddHeader (udp);
p->AddHeader (ipv4);
std::cout << "full packet size=" << p.GetSize () << std::endl;
p.Print (std::cout, printer);
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);
Ptr<Packet> p1 = p->CreateFragment (0, 2);
Ptr<Packet> p2 = p->CreateFragment (2, 1000);
Ptr<Packet> p3 = p->CreateFragment (1002, 26);
std::cout << "fragment1" << std::endl;
p1.Print (std::cout, printer);
p1->Print (std::cout, printer);
std::cout << std::endl;
std::cout << "fragment2" << std::endl;
p2.Print (std::cout, printer);
p2->Print (std::cout, printer);
std::cout << std::endl;
std::cout << "fragment3" << std::endl;
p3.Print (std::cout, printer);
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);
Ptr<Packet> aggregate = p1->Copy ();
aggregate->AddAtEnd (p2);
aggregate->AddAtEnd (p3);
std::cout << "aggregated" << std::endl;
aggregate.Print (std::cout, printer);
aggregate->Print (std::cout, printer);
std::cout << std::endl;
}
+5 -5
View File
@@ -116,20 +116,20 @@ int main (int argc, char *argv[])
tag.SetSimpleValue (0x56);
// store the tag in a packet.
Packet p;
p.AddTag (tag);
Ptr<Packet> p = Create<Packet> ();
p->AddTag (tag);
// create a copy of the packet
Packet aCopy = p;
Ptr<Packet> aCopy = p->Copy ();
// read the tag from the packet copy
MyTag tagCopy;
p.PeekTag (tagCopy);
p->PeekTag (tagCopy);
// the copy and the original are the same !
NS_ASSERT (tagCopy.GetSimpleValue () == tag.GetSimpleValue ());
aCopy.PrintTags (std::cout);
aCopy->PrintTags (std::cout);
std::cout << std::endl;
return 0;
+67
View File
@@ -0,0 +1,67 @@
/* -*- 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 "ns3/propagation-loss-model.h"
#include "ns3/default-value.h"
#include "ns3/static-mobility-model.h"
using namespace ns3;
static void
PrintOne (double minTxpower, double maxTxpower, double stepTxpower, double min, double max, double step)
{
Ptr<StaticMobilityModel> a = CreateObject<StaticMobilityModel> ();
Ptr<StaticMobilityModel> b = CreateObject<StaticMobilityModel> ();
Ptr<PropagationLossModel> model = PropagationLossModel::CreateDefault ();
a->SetPosition (Vector (0.0, 0.0, 0.0));
for (double x = min; x < max; x+= step)
{
b->SetPosition (Vector (x, 0.0, 0.0));
std::cout << x << " ";
for (double txpower = minTxpower; txpower < maxTxpower; txpower += stepTxpower)
{
double rxPowerDbm = model->GetRxPower (txpower, a, b);
std::cout << rxPowerDbm << " ";
}
std::cout << std::endl;
}
}
int main (int argc, char *argv[])
{
#if 0
DefaultValue::Bind ("PropagationLossModelType", "Friis");
DefaultValue::Bind ("FriisPropagationLossLambda", "0.6");
DefaultValue::Bind ("FriisPropagationLossSystemLoss", "1.0");
PrintOne (-10, 20, 5, 0, 1000, 5);
#endif
DefaultValue::Bind ("PropagationLossModelType", "LogDistance");
DefaultValue::Bind ("LogDistancePropagationLossReferenceDistance", "1.0");
DefaultValue::Bind ("LogDistancePropagationLossReferenceType", "Random");
DefaultValue::Bind ("RandomPropagationLossDistribution", "Constant:10");
DefaultValue::Bind ("LogDistancePropagationLossExponent", "4");
PrintOne (-10, 20, 5, 0, 10000, 2);
return 0;
}
+2 -2
View File
@@ -49,7 +49,7 @@ 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> ();
Ptr<A> a = CreateObject<A> ();
a->Method ();
Ptr<A> prev = StoreA (a);
NS_ASSERT (prev == 0);
@@ -58,7 +58,7 @@ int main (int argc, char *argv[])
{
// 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> a = CreateObject<A> ();
Ptr<A> prev = StoreA (a);
// call method on object
prev->Method ();
-282
View File
@@ -1,282 +0,0 @@
/* -*- 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/log.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)
{
NS_LOG_FUNCTION;
// pre-dispatch asserts
NS_LOG_LOGIC ("pre-condition");
domethodA ();
NS_LOG_LOGIC ("post-condition");
// 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_LOG_FUNCTION;
}
AnImplementation::AnImplementation (void)
{
NS_LOG_FUNCTION;
// enable our interface
SetInterfaceId (AnImplementation::iid);
}
void
AnImplementation::domethodA ()
{
NS_LOG_FUNCTION;
}
//
// 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_LOG_FUNCTION;
}
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_LOG_FUNCTION;
}
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;
}
+1 -1
View File
@@ -38,7 +38,7 @@ int main (int argc, char *argv[])
std::vector<Ptr<Object> > objects;
for (uint32_t i = 0; i < 10000; i++)
{
Ptr<MobilityModelNotifier> notifier = Create<MobilityModelNotifier> ();
Ptr<MobilityModelNotifier> notifier = CreateObject<MobilityModelNotifier> ();
notifier->TraceConnect ("/course-change", MakeCallback (&CourseChange));
objects.push_back (notifier);
}
+2 -2
View File
@@ -45,8 +45,8 @@ int main (int argc, char *argv[])
for (uint32_t i = 0; i < 100; i++)
{
Ptr<Node> node = Create<Node> ();
node->AddInterface (Create<MobilityModelNotifier> ());
Ptr<Node> node = CreateObject<Node> ();
node->AggregateObject (CreateObject<MobilityModelNotifier> ());
}
topology.Layout (NodeList::Begin (), NodeList::End ());
+6 -6
View File
@@ -14,7 +14,7 @@ static void
GenerateTraffic (Ptr<Socket> socket, uint32_t size)
{
std::cout << "at=" << Simulator::Now ().GetSeconds () << "s, tx bytes=" << size << std::endl;
socket->Send (Packet (size));
socket->Send (Create<Packet> (size));
if (size > 0)
{
Simulator::Schedule (Seconds (0.5), &GenerateTraffic, socket, size - 50);
@@ -26,9 +26,9 @@ GenerateTraffic (Ptr<Socket> socket, uint32_t size)
}
static void
SocketPrinter (Ptr<Socket> socket, const Packet &packet, const Address &from)
SocketPrinter (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from)
{
std::cout << "at=" << Simulator::Now ().GetSeconds () << "s, rx bytes=" << packet.GetSize () << std::endl;
std::cout << "at=" << Simulator::Now ().GetSeconds () << "s, rx bytes=" << packet->GetSize () << std::endl;
}
static void
@@ -40,10 +40,10 @@ PrintTraffic (Ptr<Socket> socket)
void
RunSimulation (void)
{
Ptr<Node> a = Create<InternetNode> ();
Ptr<Node> a = CreateObject<InternetNode> ();
InterfaceId iid = InterfaceId::LookupByName ("Udp");
Ptr<SocketFactory> socketFactory = a->QueryInterface<SocketFactory> (iid);
TypeId tid = TypeId::LookupByName ("Udp");
Ptr<SocketFactory> socketFactory = a->GetObject<SocketFactory> (tid);
Ptr<Socket> sink = socketFactory->CreateSocket ();
InetSocketAddress local = InetSocketAddress (Ipv4Address::GetAny (), 80);
+14
View File
@@ -38,6 +38,20 @@ def build(bld):
['core', 'simulator', 'mobility'])
obj.source = 'main-random-topology.cc'
obj = bld.create_ns3_program('main-adhoc-wifi',
['core', 'simulator', 'mobility', 'wifi'])
obj.source = 'main-adhoc-wifi.cc'
obj = bld.create_ns3_program('main-ap-wifi',
['core', 'simulator', 'mobility', 'wifi'])
obj.source = 'main-ap-wifi.cc'
obj = bld.create_ns3_program('main-random-walk',
['core', 'simulator', 'mobility'])
obj.source = 'main-random-walk.cc'
obj = bld.create_ns3_program('main-propagation-loss',
['core', 'simulator', 'mobility', 'wifi'])
obj.source = 'main-propagation-loss.cc'
+32 -21
View File
@@ -33,6 +33,7 @@
#include "ns3/socket-factory.h"
#include "ns3/default-value.h"
#include "ns3/packet.h"
#include "ns3/composite-trace-resolver.h"
#include "onoff-application.h"
NS_LOG_COMPONENT_DEFINE ("OnOffApplication");
@@ -52,20 +53,20 @@ static NumericDefaultValue<uint32_t> g_defaultSize ("OnOffApplicationPacketSize"
OnOffApplication::OnOffApplication(Ptr<Node> n,
const Address &remote,
std::string iid,
std::string tid,
const RandomVariable& ontime,
const RandomVariable& offtime)
: Application(n),
m_cbrRate (g_defaultRate.GetValue ())
{
Construct (n, remote, iid,
Construct (n, remote, tid,
ontime, offtime,
g_defaultSize.GetValue ());
}
OnOffApplication::OnOffApplication(Ptr<Node> n,
const Address &remote,
std::string iid,
std::string tid,
const RandomVariable& ontime,
const RandomVariable& offtime,
DataRate rate,
@@ -74,13 +75,13 @@ OnOffApplication::OnOffApplication(Ptr<Node> n,
m_cbrRate (rate)
{
NS_LOG_FUNCTION;
Construct (n, remote, iid, ontime, offtime, size);
Construct (n, remote, tid, ontime, offtime, size);
}
void
OnOffApplication::Construct (Ptr<Node> n,
const Address &remote,
std::string iid,
std::string tid,
const RandomVariable& onTime,
const RandomVariable& offTime,
uint32_t size)
@@ -90,14 +91,14 @@ OnOffApplication::Construct (Ptr<Node> n,
m_socket = 0;
m_peer = remote;
m_connected = false;
m_onTime = onTime.Copy ();
m_offTime = offTime.Copy ();
m_onTime = onTime;
m_offTime = offTime;
m_pktSize = size;
m_residualBits = 0;
m_lastStartTime = Seconds (0);
m_maxBytes = 0xffffffff;
m_maxBytes = 0;
m_totBytes = 0;
m_iid = iid;
m_tid = tid;
}
OnOffApplication::~OnOffApplication()
@@ -135,12 +136,6 @@ OnOffApplication::DoDispose (void)
NS_LOG_FUNCTION;
m_socket = 0;
delete m_onTime;
delete m_offTime;
m_onTime = 0;
m_offTime = 0;
// chain up
Application::DoDispose ();
}
@@ -153,8 +148,8 @@ 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);
TypeId tid = TypeId::LookupByName (m_tid);
Ptr<SocketFactory> socketFactory = GetNode ()->GetObject<SocketFactory> (tid);
m_socket = socketFactory->CreateSocket ();
m_socket->Bind ();
m_socket->Connect (m_peer);
@@ -194,6 +189,7 @@ void OnOffApplication::StopSending()
NS_LOG_FUNCTION;
Simulator::Cancel(m_sendEvent);
m_socket->Close ();
}
// Private helpers
@@ -201,7 +197,7 @@ void OnOffApplication::ScheduleNextTx()
{
NS_LOG_FUNCTION;
if (m_totBytes < m_maxBytes)
if (m_maxBytes == 0 || m_totBytes < m_maxBytes)
{
uint32_t bits = m_pktSize * 8 - m_residualBits;
NS_LOG_LOGIC ("bits = " << bits);
@@ -221,7 +217,7 @@ void OnOffApplication::ScheduleStartEvent()
{ // Schedules the event to start sending data (switch to the "On" state)
NS_LOG_FUNCTION;
Time offInterval = Seconds(m_offTime->GetValue());
Time offInterval = Seconds(m_offTime.GetValue());
NS_LOG_LOGIC ("start at " << offInterval);
m_startStopEvent = Simulator::Schedule(offInterval, &OnOffApplication::StartSending, this);
}
@@ -230,7 +226,7 @@ void OnOffApplication::ScheduleStopEvent()
{ // Schedules the event to stop sending data (switch to "Off" state)
NS_LOG_FUNCTION;
Time onInterval = Seconds(m_onTime->GetValue());
Time onInterval = Seconds(m_onTime.GetValue());
Simulator::Schedule(onInterval, &OnOffApplication::StopSending, this);
}
@@ -240,7 +236,9 @@ void OnOffApplication::SendPacket()
NS_LOG_FUNCTION;
NS_ASSERT (m_sendEvent.IsExpired ());
m_socket->Send(Packet (m_pktSize));
Ptr<Packet> packet = Create<Packet> (m_pktSize);
m_txTrace (packet);
m_socket->Send (packet);
m_totBytes += m_pktSize;
m_lastStartTime = Simulator::Now();
m_residualBits = 0;
@@ -261,4 +259,17 @@ void OnOffApplication::ConnectionFailed(Ptr<Socket>)
cout << "OnOffApplication, Connection Failed" << endl;
}
Ptr<TraceResolver>
OnOffApplication::GetTraceResolver (void) const
{
Ptr<CompositeTraceResolver> resolver = Create<CompositeTraceResolver> ();
resolver->AddSource ("tx",
TraceDoc ("A new packet is created and is sent",
"Ptr<const Packet>",
"The newly-created packet."),
m_txTrace);
resolver->SetParentResolver (Application::GetTraceResolver ());
return resolver;
}
} // Namespace ns3
+16 -8
View File
@@ -29,6 +29,8 @@
#include "ns3/event-id.h"
#include "ns3/ptr.h"
#include "ns3/data-rate.h"
#include "ns3/callback-trace-source.h"
#include "ns3/random-variable.h"
namespace ns3 {
@@ -53,20 +55,24 @@ public:
/**
* \param n node associated to this application
* \param remote remote ip address
* \param iid
* \param tid TypeId of the socket factory to use. Note this
* factory should create sockets compatible with the specified
* remote address.
* \param ontime on time random variable
* \param offtime off time random variable
*/
OnOffApplication(Ptr<Node> n,
const Address &remote,
std::string iid,
std::string tid,
const RandomVariable& ontime,
const RandomVariable& offtime);
/**
* \param n node associated to this application
* \param remote remote ip address
* \param iid
* \param tid TypeId of the socket factory to use. Note this
* factory should create sockets compatible with the specified
* remote address.
* \param ontime on time random variable
* \param offtime off time random variable
* \param rate data rate when on
@@ -74,7 +80,7 @@ public:
*/
OnOffApplication(Ptr<Node> n,
const Address &remote,
std::string iid,
std::string tid,
const RandomVariable& ontime,
const RandomVariable& offtime,
DataRate rate,
@@ -109,7 +115,7 @@ private:
void Construct (Ptr<Node> n,
const Address &remote,
std::string iid,
std::string tid,
const RandomVariable& ontime,
const RandomVariable& offtime,
uint32_t size);
@@ -123,8 +129,8 @@ private:
Ptr<Socket> m_socket; // Associated socket
Address m_peer; // Peer address
bool m_connected; // True if connected
RandomVariable* m_onTime; // rng for On Time
RandomVariable* m_offTime; // rng for Off Time
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
@@ -134,9 +140,11 @@ private:
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;
std::string m_tid;
CallbackTraceSource<Ptr<const Packet> > m_txTrace;
private:
virtual Ptr<TraceResolver> GetTraceResolver (void) const;
void ScheduleNextTx();
void ScheduleStartEvent();
void ScheduleStopEvent();
+1 -1
View File
@@ -1,7 +1,7 @@
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
def build(bld):
module = bld.create_ns3_module('onoff', ['core'])
module = bld.create_ns3_module('onoff', ['core', 'simulator', 'node'])
module.source = [
'onoff-application.cc',
]
+39 -13
View File
@@ -25,6 +25,7 @@
#include "ns3/simulator.h"
#include "ns3/socket-factory.h"
#include "ns3/packet.h"
#include "ns3/composite-trace-resolver.h"
#include "packet-sink.h"
using namespace std;
@@ -37,20 +38,20 @@ NS_LOG_COMPONENT_DEFINE ("PacketSinkApplication");
PacketSink::PacketSink (Ptr<Node> n,
const Address &local,
std::string iid)
std::string tid)
: Application(n)
{
Construct (n, local, iid);
Construct (n, local, tid);
}
void
PacketSink::Construct (Ptr<Node> n,
const Address &local,
std::string iid)
std::string tid)
{
m_socket = 0;
m_local = local;
m_iid = iid;
m_tid = tid;
}
PacketSink::~PacketSink()
@@ -72,37 +73,62 @@ void PacketSink::StartApplication() // Called at time specified by Start
// Create the socket if not already
if (!m_socket)
{
InterfaceId iid = InterfaceId::LookupByName (m_iid);
TypeId tid = TypeId::LookupByName (m_tid);
Ptr<SocketFactory> socketFactory =
GetNode ()->QueryInterface<SocketFactory> (iid);
GetNode ()->GetObject<SocketFactory> (tid);
m_socket = socketFactory->CreateSocket ();
m_socket->Bind (m_local);
m_socket->Listen (0);
}
m_socket->SetRecvCallback (MakeCallback(&PacketSink::Receive, this));
m_socket->SetAcceptCallback (
MakeNullCallback<bool, Ptr<Socket>, const Address &> (),
MakeNullCallback<void, Ptr<Socket>, const Address&> (),
MakeCallback(&PacketSink::CloseConnection, this) );
}
void PacketSink::StopApplication() // Called at time specified by Stop
{
if (!m_socket)
if (m_socket)
{
m_socket->SetRecvCallback (MakeNullCallback<void, Ptr<Socket>,
const Packet &, const Address &> ());
Ptr<Packet>, const Address &> ());
}
}
// This LOG output inspired by the application on Joseph Kopena's wiki
void PacketSink::Receive(Ptr<Socket> socket, const Packet &packet,
void PacketSink::Receive(Ptr<Socket> socket, Ptr<Packet> packet,
const Address &from)
{
if (InetSocketAddress::IsMatchingType (from))
{
InetSocketAddress address = InetSocketAddress::ConvertFrom (from);
NS_LOG_INFO ("Received " << packet.GetSize() << " bytes from " <<
NS_LOG_INFO ("Received " << packet->GetSize() << " bytes from " <<
address.GetIpv4() << " [" << address << "]---'" <<
packet.PeekData() << "'");
// TODO: Add a tracing source here
packet->PeekData() << "'");
}
m_rxTrace (packet, from);
}
void PacketSink::CloseConnection (Ptr<Socket> socket)
{
socket->Close ();
}
Ptr<TraceResolver>
PacketSink::GetTraceResolver (void) const
{
Ptr<CompositeTraceResolver> resolver = Create<CompositeTraceResolver> ();
resolver->AddSource ("rx",
TraceDoc ("A new packet has been received",
"Ptr<const Packet>",
"The newly-received packet.",
"const Address &",
"The source address of the received packet."),
m_rxTrace);
resolver->SetParentResolver (Application::GetTraceResolver ());
return resolver;
}
} // Namespace ns3
+11 -5
View File
@@ -24,6 +24,8 @@
#include "ns3/application.h"
#include "ns3/event-id.h"
#include "ns3/ptr.h"
#include "ns3/callback-trace-source.h"
#include "ns3/address.h"
namespace ns3 {
@@ -54,11 +56,11 @@ public:
/**
* \param n node associated to this application
* \param local local address to bind to
* \param iid string to identify transport protocol of interest
* \param tid string to identify transport protocol of interest
*/
PacketSink (Ptr<Node> n,
const Address &local,
std::string iid);
std::string tid);
virtual ~PacketSink ();
@@ -68,16 +70,20 @@ 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
// inherited from Object base class.
virtual Ptr<TraceResolver> GetTraceResolver (void) const;
void Construct (Ptr<Node> n,
const Address &local,
std::string iid);
std::string tid);
virtual void Receive (Ptr<Socket> socket, const Packet& packet, const Address& from);
virtual void Receive (Ptr<Socket> socket, Ptr<Packet> packet, const Address& from);
virtual void CloseConnection (Ptr<Socket> socket);
Ptr<Socket> m_socket; // Associated socket
Address m_local; // Local address to bind to
std::string m_iid; // Protocol name (e.g., "Udp")
std::string m_tid; // Protocol name (e.g., "Udp")
CallbackTraceSource<Ptr<const Packet>, const Address &> m_rxTrace;
};
+8 -9
View File
@@ -91,16 +91,15 @@ UdpEchoClient::StartApplication (void)
if (!m_socket)
{
InterfaceId iid = InterfaceId::LookupByName ("Udp");
TypeId tid = TypeId::LookupByName ("Udp");
Ptr<SocketFactory> socketFactory =
GetNode ()->QueryInterface<SocketFactory> (iid);
GetNode ()->GetObject<SocketFactory> (tid);
m_socket = socketFactory->CreateSocket ();
m_socket->Bind ();
m_socket->Connect (m_peer);
}
m_socket->SetRecvCallback((Callback<void, Ptr<Socket>, const Packet &,
const Address &>) MakeCallback(&UdpEchoClient::Receive, this));
m_socket->SetRecvCallback(MakeCallback(&UdpEchoClient::Receive, this));
ScheduleTransmit (Seconds(0.));
}
@@ -112,8 +111,8 @@ UdpEchoClient::StopApplication ()
if (!m_socket)
{
m_socket->SetRecvCallback((Callback<void, Ptr<Socket>, const Packet &,
const Address &>) NULL);
m_socket->SetRecvCallback(MakeNullCallback<void, Ptr<Socket>, Ptr<Packet>,
const Address &> ());
}
Simulator::Cancel(m_sendEvent);
@@ -133,7 +132,7 @@ UdpEchoClient::Send (void)
NS_ASSERT (m_sendEvent.IsExpired ());
Packet p (m_size);
Ptr<Packet> p = Create<Packet> (m_size);
m_socket->Send (p);
++m_sent;
@@ -148,7 +147,7 @@ UdpEchoClient::Send (void)
void
UdpEchoClient::Receive(
Ptr<Socket> socket,
const Packet &packet,
Ptr<Packet> packet,
const Address &from)
{
NS_LOG_FUNCTION;
@@ -157,7 +156,7 @@ UdpEchoClient::Receive(
if (InetSocketAddress::IsMatchingType (from))
{
InetSocketAddress address = InetSocketAddress::ConvertFrom (from);
NS_LOG_INFO ("Received " << packet.GetSize() << " bytes from " <<
NS_LOG_INFO ("Received " << packet->GetSize() << " bytes from " <<
address.GetIpv4());
}
}
+1 -1
View File
@@ -50,7 +50,7 @@ private:
void ScheduleTransmit (Time dt);
void Send (void);
void Receive(Ptr<Socket> socket, const Packet &packet, const Address &from);
void Receive(Ptr<Socket> socket, Ptr<Packet> packet, const Address &from);
Ptr<Node> m_node;
Ipv4Address m_serverAddress;
+6 -6
View File
@@ -77,9 +77,9 @@ UdpEchoServer::StartApplication (void)
if (!m_socket)
{
InterfaceId iid = InterfaceId::LookupByName ("Udp");
TypeId tid = TypeId::LookupByName ("Udp");
Ptr<SocketFactory> socketFactory =
GetNode ()->QueryInterface<SocketFactory> (iid);
GetNode ()->GetObject<SocketFactory> (tid);
m_socket = socketFactory->CreateSocket ();
m_socket->Bind (m_local);
}
@@ -94,15 +94,15 @@ UdpEchoServer::StopApplication ()
if (!m_socket)
{
m_socket->SetRecvCallback (MakeNullCallback<void, Ptr<Socket>,
const Packet &, const Address &> ());
m_socket->SetRecvCallback(MakeNullCallback<void, Ptr<Socket>,
Ptr<Packet>, const Address &> ());
}
}
void
UdpEchoServer::Receive(
Ptr<Socket> socket,
const Packet &packet,
Ptr<Packet> packet,
const Address &from)
{
NS_LOG_FUNCTION;
@@ -111,7 +111,7 @@ UdpEchoServer::Receive(
if (InetSocketAddress::IsMatchingType (from))
{
InetSocketAddress address = InetSocketAddress::ConvertFrom (from);
NS_LOG_INFO ("Received " << packet.GetSize() << " bytes from " <<
NS_LOG_INFO ("Received " << packet->GetSize() << " bytes from " <<
address.GetIpv4());
NS_LOG_LOGIC ("Echoing packet");
+1 -1
View File
@@ -44,7 +44,7 @@ private:
virtual void StartApplication (void);
virtual void StopApplication (void);
void Receive(Ptr<Socket> socket, const Packet &packet, const Address &from);
void Receive(Ptr<Socket> socket, Ptr<Packet> packet, const Address &from);
Ptr<Node> m_node;
uint16_t m_port;
+1 -1
View File
@@ -105,7 +105,7 @@ ChunkRegistry::GetName (uint32_t uid, uint8_t *instance)
void
ChunkRegistry::InvokePrintCallback (uint32_t uid, uint8_t *instance, std::ostream &os,
uint32_t packetUid, uint32_t size,
Ptr<CallbackImplBase> callback)
CallbackBase callback)
{
InfoVector *vec = GetInfoVector ();
NS_ASSERT (uid >= 1 && uid <= vec->size ());
+4 -4
View File
@@ -54,7 +54,7 @@ public:
static bool IsTrailer (uint32_t uid);
static void InvokePrintCallback (uint32_t uid, uint8_t *instance, std::ostream &os,
uint32_t packetUid, uint32_t size,
Ptr<CallbackImplBase> callback);
CallbackBase callback);
private:
typedef uint8_t *(*GetStaticInstanceCb) (void);
typedef uint32_t (*DeserializeCb) (uint8_t *, Buffer::Iterator);
@@ -62,7 +62,7 @@ private:
typedef std::string (*GetNameCb) (uint8_t *);
typedef void (*InvokePrintCallbackCb) (uint8_t *instance, std::ostream &os,
uint32_t packetUid, uint32_t size,
Ptr<CallbackImplBase> callback);
CallbackBase callback);
struct Info {
std::string uidString;
bool isHeader;
@@ -85,7 +85,7 @@ private:
template <typename T>
static void DoInvokePrintCallback (uint8_t *instance, std::ostream &os,
uint32_t packetUid, uint32_t size,
Ptr<CallbackImplBase> callback);
CallbackBase callback);
template <typename T>
static uint32_t GetUid (bool isHeader, std::string uidString);
@@ -167,7 +167,7 @@ template <typename T>
void
ChunkRegistry::DoInvokePrintCallback (uint8_t *instance, std::ostream &os,
uint32_t packetUid, uint32_t size,
Ptr<CallbackImplBase> callback)
CallbackBase callback)
{
T *obj = reinterpret_cast<T *> (instance);
Callback<void,std::ostream&,uint32_t,uint32_t,const T*> cb;
+48 -38
View File
@@ -28,22 +28,30 @@
#include "ns3/log.h"
#include "ns3/random-variable.h"
#include "ns3/default-value.h"
#include "ns3/type-id-default-value.h"
NS_LOG_COMPONENT_DEFINE ("ErrorModel");
namespace ns3 {
static ClassIdDefaultValue g_classIdErrorModelDefaultValue ("ErrorModel",
"Error Model", ErrorModel::iid, "RateErrorModel");
static TypeIdDefaultValue g_interfaceIdErrorModelDefaultValue ("ErrorModel",
"Error Model",
ErrorModel::GetTypeId (),
"RateErrorModel");
const InterfaceId ErrorModel::iid =
MakeInterfaceId ("ErrorModel", Object::iid);
NS_OBJECT_ENSURE_REGISTERED (ErrorModel);
TypeId ErrorModel::GetTypeId (void)
{
static TypeId tid = TypeId ("ErrorModel")
.SetParent<Object> ();
return tid;
}
ErrorModel::ErrorModel () :
m_enable (true)
{
NS_LOG_FUNCTION;
SetInterfaceId (ErrorModel::iid);
}
ErrorModel::~ErrorModel ()
@@ -55,14 +63,13 @@ Ptr<ErrorModel>
ErrorModel::CreateDefault (void)
{
NS_LOG_FUNCTION;
ClassId classId = g_classIdErrorModelDefaultValue.GetValue ();
Ptr<ErrorModel> em = ComponentManager::Create<ErrorModel> (classId,
ErrorModel::iid);
TypeId interfaceId = g_interfaceIdErrorModelDefaultValue.GetValue ();
Ptr<ErrorModel> em = interfaceId.CreateObject ()->GetObject<ErrorModel> ();
return em;
}
bool
ErrorModel::IsCorrupt (Packet& p)
ErrorModel::IsCorrupt (Ptr<Packet> p)
{
NS_LOG_FUNCTION;
bool result;
@@ -104,13 +111,6 @@ ErrorModel::IsEnabled (void) const
// RateErrorModel
//
const InterfaceId RateErrorModel::iid =
MakeInterfaceId ("RateErrorModel", ErrorModel::iid);
const ClassId RateErrorModel::cid =
MakeClassId<RateErrorModel> ("RateErrorModel", ErrorModel::iid,
RateErrorModel::iid);
// Defaults for rate/size
static NumericDefaultValue<double> g_defaultRateErrorModelErrorRate
("RateErrorModelErrorRate", "The error rate for the error model", 0.0);
@@ -123,20 +123,29 @@ static EnumDefaultValue<enum ErrorUnit>
EU_BIT, "EU_BIT",
0, (void*)0);
NS_OBJECT_ENSURE_REGISTERED (RateErrorModel);
TypeId RateErrorModel::GetTypeId (void)
{
static TypeId tid = TypeId ("RateErrorModel")
.SetParent<ErrorModel> ()
.AddConstructor<RateErrorModel> ();
return tid;
}
RateErrorModel::RateErrorModel () :
m_unit (g_defaultRateErrorModelErrorUnit.GetValue() ),
m_rate (g_defaultRateErrorModelErrorRate.GetValue() )
{
NS_LOG_FUNCTION;
// Assume a uniform random variable if user does not specify
m_ranvar = new UniformVariable ();
SetInterfaceId (RateErrorModel::iid);
m_ranvar = UniformVariable ();
}
RateErrorModel::~RateErrorModel ()
{
NS_LOG_FUNCTION;
delete m_ranvar;
}
enum ErrorUnit
@@ -171,12 +180,11 @@ void
RateErrorModel::SetRandomVariable (const RandomVariable &ranvar)
{
NS_LOG_FUNCTION;
delete m_ranvar;
m_ranvar = ranvar.Copy ();
m_ranvar = ranvar;
}
bool
RateErrorModel::DoCorrupt (Packet& p)
RateErrorModel::DoCorrupt (Ptr<Packet> p)
{
NS_LOG_FUNCTION;
if (!m_enable)
@@ -199,28 +207,28 @@ RateErrorModel::DoCorrupt (Packet& p)
}
bool
RateErrorModel::DoCorruptPkt (Packet& p)
RateErrorModel::DoCorruptPkt (Ptr<Packet> p)
{
NS_LOG_FUNCTION;
return (m_ranvar->GetValue () < m_rate);
return (m_ranvar.GetValue () < m_rate);
}
bool
RateErrorModel::DoCorruptByte (Packet& p)
RateErrorModel::DoCorruptByte (Ptr<Packet> p)
{
NS_LOG_FUNCTION;
// compute pkt error rate, assume uniformly distributed byte error
double per = 1 - pow (1.0 - m_rate, p.GetSize ());
return (m_ranvar->GetValue () < per);
double per = 1 - pow (1.0 - m_rate, p->GetSize ());
return (m_ranvar.GetValue () < per);
}
bool
RateErrorModel::DoCorruptBit(Packet& p)
RateErrorModel::DoCorruptBit(Ptr<Packet> p)
{
NS_LOG_FUNCTION;
// compute pkt error rate, assume uniformly distributed bit error
double per = 1 - pow (1.0 - m_rate, (8 * p.GetSize ()) );
return (m_ranvar->GetValue () < per);
double per = 1 - pow (1.0 - m_rate, (8 * p->GetSize ()) );
return (m_ranvar.GetValue () < per);
}
void
@@ -234,17 +242,19 @@ RateErrorModel::DoReset (void)
// ListErrorModel
//
const InterfaceId ListErrorModel::iid =
MakeInterfaceId ("ListErrorModel", ErrorModel::iid);
NS_OBJECT_ENSURE_REGISTERED (ListErrorModel);
const ClassId ListErrorModel::cid =
MakeClassId<ListErrorModel> ("ListErrorModel", ErrorModel::iid,
ListErrorModel::iid);
TypeId ListErrorModel::GetTypeId (void)
{
static TypeId tid = TypeId ("ListErrorModel")
.SetParent<ErrorModel> ()
.AddConstructor<ListErrorModel> ();
return tid;
}
ListErrorModel::ListErrorModel ()
{
NS_LOG_FUNCTION;
SetInterfaceId (ListErrorModel::iid);
}
ListErrorModel::~ListErrorModel ()
@@ -270,14 +280,14 @@ ListErrorModel::SetList (const std::list<uint32_t> &packetlist)
// converted to a dynamically-sized array of uint32_t to avoid
// list iteration below.
bool
ListErrorModel::DoCorrupt (Packet& p)
ListErrorModel::DoCorrupt (Ptr<Packet> p)
{
NS_LOG_FUNCTION;
if (!m_enable)
{
return false;
}
uint32_t uid = p.GetUid ();
uint32_t uid = p->GetUid ();
for (PacketListCI i = m_packetList.begin ();
i != m_packetList.end (); i++)
{
+15 -18
View File
@@ -23,12 +23,11 @@
#include <list>
#include "ns3/object.h"
#include "ns3/component-manager.h"
#include "ns3/random-variable.h"
namespace ns3 {
class Packet;
class RandomVariable;
/**
* \brief General error model that can be used to corrupt packets
@@ -37,7 +36,7 @@ class RandomVariable;
* It is part of the Object framework and can be aggregated to
* other ns3 objects and handled by the Ptr class.
*
* The main method is IsCorrupt(Packet& p) which returns true if
* The main method is IsCorrupt(Ptr<Packet> p) which returns true if
* the packet is to be corrupted according to the underlying model.
* Depending on the error model, the packet itself may have its packet
* data buffer errored or not, or side information may be returned to
@@ -48,11 +47,11 @@ class RandomVariable;
* Typical code (simplified) to use an ErrorModel may look something like
* this:
* \code
* Ptr<ErrorModel> rem = Create<RateErrorModel> ();
* Ptr<ErrorModel> rem = CreateObject<RateErrorModel> ();
* rem->SetRandomVariable (UniformVariable ());
* rem->SetRate (0.001);
* ...
* Packet p;
* Ptr<Packet> p;
* if (rem->IsCorrupt (p))
* {
* dropTrace(p);
@@ -67,7 +66,7 @@ class RandomVariable;
class ErrorModel : public Object
{
public:
static const InterfaceId iid;
static TypeId GetTypeId (void);
/**
* A factory method to generate a preconfigured default ErrorModel for use
* \return an ErrorModel smart pointer that is the default ErrorModel
@@ -82,7 +81,7 @@ public:
* \returns true if the Packet is to be considered as errored/corrupted
* \param pkt Packet to apply error model to
*/
bool IsCorrupt (Packet& pkt);
bool IsCorrupt (Ptr<Packet> pkt);
/**
* Reset any state associated with the error model
*/
@@ -107,7 +106,7 @@ private:
/*
* These methods must be implemented by subclasses
*/
virtual bool DoCorrupt (Packet&) = 0;
virtual bool DoCorrupt (Ptr<Packet>) = 0;
virtual void DoReset (void) = 0;
};
@@ -137,8 +136,7 @@ enum ErrorUnit
class RateErrorModel : public ErrorModel
{
public:
static const InterfaceId iid;
static const ClassId cid;
static TypeId GetTypeId (void);
RateErrorModel ();
virtual ~RateErrorModel ();
@@ -167,16 +165,16 @@ public:
void SetRandomVariable (const RandomVariable &ranvar);
private:
virtual bool DoCorrupt (Packet& p);
virtual bool DoCorruptPkt (Packet& p);
virtual bool DoCorruptByte (Packet& p);
virtual bool DoCorruptBit (Packet& p);
virtual bool DoCorrupt (Ptr<Packet> p);
virtual bool DoCorruptPkt (Ptr<Packet> p);
virtual bool DoCorruptByte (Ptr<Packet> p);
virtual bool DoCorruptBit (Ptr<Packet> p);
virtual void DoReset (void);
enum ErrorUnit m_unit;
double m_rate;
RandomVariable* m_ranvar;
RandomVariable m_ranvar;
};
/**
@@ -204,8 +202,7 @@ private:
class ListErrorModel : public ErrorModel
{
public:
static const InterfaceId iid;
static const ClassId cid;
static TypeId GetTypeId (void);
ListErrorModel ();
virtual ~ListErrorModel ();
@@ -221,7 +218,7 @@ public:
void SetList (const std::list<uint32_t> &packetlist);
private:
virtual bool DoCorrupt (Packet& p);
virtual bool DoCorrupt (Ptr<Packet> p);
virtual void DoReset (void);
typedef std::list<uint32_t> PacketList;
+71 -71
View File
@@ -199,7 +199,7 @@ class PacketMetadataTest : public Test {
public:
PacketMetadataTest ();
virtual ~PacketMetadataTest ();
bool CheckHistory (Packet p, const char *file, int line, uint32_t n, ...);
bool CheckHistory (Ptr<Packet> p, const char *file, int line, uint32_t n, ...);
virtual bool RunTests (void);
private:
template <int N>
@@ -217,7 +217,7 @@ private:
template <int N>
void RegisterTrailer (void);
void CleanupPrints (void);
Packet DoAddHeader (Packet p);
Ptr<Packet> DoAddHeader (Ptr<Packet> p);
bool Check (const char *file, int line, std::list<int> expected);
@@ -358,7 +358,7 @@ PacketMetadataTest::Check (const char *file, int line, std::list<int> expected)
}
bool
PacketMetadataTest::CheckHistory (Packet p, const char *file, int line, uint32_t n, ...)
PacketMetadataTest::CheckHistory (Ptr<Packet> p, const char *file, int line, uint32_t n, ...)
{
m_headerError = false;
m_trailerError = false;
@@ -373,7 +373,7 @@ PacketMetadataTest::CheckHistory (Packet p, const char *file, int line, uint32_t
va_end (ap);
m_printer.PrintForward ();
p.Print (Failure (), m_printer);
p->Print (Failure (), m_printer);
bool ok = Check (file, line, expected);
CleanupPrints ();
if (!ok)
@@ -382,7 +382,7 @@ PacketMetadataTest::CheckHistory (Packet p, const char *file, int line, uint32_t
}
m_printer.PrintBackward ();
p.Print (Failure (), m_printer);
p->Print (Failure (), m_printer);
expected.reverse ();
ok = Check (file, line, expected);
CleanupPrints ();
@@ -393,25 +393,25 @@ PacketMetadataTest::CheckHistory (Packet p, const char *file, int line, uint32_t
{ \
HistoryHeader<n> header; \
RegisterHeader<n> (); \
p.AddHeader (header); \
p->AddHeader (header); \
}
#define ADD_TRAILER(p, n) \
{ \
HistoryTrailer<n> trailer; \
RegisterTrailer<n> (); \
p.AddTrailer (trailer); \
p->AddTrailer (trailer); \
}
#define REM_HEADER(p, n) \
{ \
HistoryHeader<n> header; \
RegisterHeader<n> (); \
p.RemoveHeader (header); \
p->RemoveHeader (header); \
}
#define REM_TRAILER(p, n) \
{ \
HistoryTrailer<n> trailer; \
RegisterTrailer<n> (); \
p.RemoveTrailer (trailer); \
p->RemoveTrailer (trailer); \
}
#define CHECK_HISTORY(p, ...) \
{ \
@@ -421,9 +421,9 @@ PacketMetadataTest::CheckHistory (Packet p, const char *file, int line, uint32_t
ok = false; \
} \
Buffer buffer; \
buffer = p.Serialize (); \
Packet otherPacket; \
otherPacket.Deserialize (buffer); \
buffer = p->Serialize (); \
Ptr<Packet> otherPacket = Create<Packet> ();\
otherPacket->Deserialize (buffer); \
if (!CheckHistory (otherPacket, __FILE__, \
__LINE__, __VA_ARGS__)) \
{ \
@@ -432,8 +432,8 @@ PacketMetadataTest::CheckHistory (Packet p, const char *file, int line, uint32_t
}
Packet
PacketMetadataTest::DoAddHeader (Packet p)
Ptr<Packet>
PacketMetadataTest::DoAddHeader (Ptr<Packet> p)
{
ADD_HEADER (p, 10);
return p;
@@ -446,14 +446,14 @@ PacketMetadataTest::RunTests (void)
PacketMetadata::Enable ();
Packet p = Packet (0);
Packet p1 = Packet (0);
Ptr<Packet> p = Create<Packet> (0);
Ptr<Packet> p1 = Create<Packet> (0);
p = Packet (10);
p = Create<Packet> (10);
ADD_TRAILER (p, 100);
CHECK_HISTORY (p, 2, 10, 100);
p = Packet (10);
p = Create<Packet> (10);
ADD_HEADER (p, 1);
ADD_HEADER (p, 2);
ADD_HEADER (p, 3);
@@ -466,7 +466,7 @@ PacketMetadataTest::RunTests (void)
CHECK_HISTORY (p, 6,
6, 5, 3, 2, 1, 10);
p = Packet (10);
p = Create<Packet> (10);
ADD_HEADER (p, 1);
ADD_HEADER (p, 2);
ADD_HEADER (p, 3);
@@ -474,7 +474,7 @@ PacketMetadataTest::RunTests (void)
CHECK_HISTORY (p, 3,
2, 1, 10);
p = Packet (10);
p = Create<Packet> (10);
ADD_HEADER (p, 1);
ADD_HEADER (p, 2);
ADD_HEADER (p, 3);
@@ -483,7 +483,7 @@ PacketMetadataTest::RunTests (void)
CHECK_HISTORY (p, 2,
1, 10);
p = Packet (10);
p = Create<Packet> (10);
ADD_HEADER (p, 1);
ADD_HEADER (p, 2);
ADD_HEADER (p, 3);
@@ -492,11 +492,11 @@ PacketMetadataTest::RunTests (void)
REM_HEADER (p, 1);
CHECK_HISTORY (p, 1, 10);
p = Packet (10);
p = Create<Packet> (10);
ADD_HEADER (p, 1);
ADD_HEADER (p, 2);
ADD_HEADER (p, 3);
p1 = p;
p1 = p->Copy ();
REM_HEADER (p1, 3);
REM_HEADER (p1, 2);
REM_HEADER (p1, 1);
@@ -524,88 +524,88 @@ PacketMetadataTest::RunTests (void)
REM_TRAILER (p, 5);
CHECK_HISTORY (p, 5,
3, 2, 1, 10, 4);
p1 = p;
p1 = p->Copy ();
REM_TRAILER (p, 4);
CHECK_HISTORY (p, 4,
3, 2, 1, 10);
CHECK_HISTORY (p1, 5,
3, 2, 1, 10, 4);
p1.RemoveAtStart (3);
p1->RemoveAtStart (3);
CHECK_HISTORY (p1, 4,
2, 1, 10, 4);
p1.RemoveAtStart (1);
p1->RemoveAtStart (1);
CHECK_HISTORY (p1, 4,
1, 1, 10, 4);
p1.RemoveAtStart (1);
p1->RemoveAtStart (1);
CHECK_HISTORY (p1, 3,
1, 10, 4);
p1.RemoveAtEnd (4);
p1->RemoveAtEnd (4);
CHECK_HISTORY (p1, 2,
1, 10);
p1.RemoveAtStart (1);
p1->RemoveAtStart (1);
CHECK_HISTORY (p1, 1, 10);
p = Packet (10);
p = Create<Packet> (10);
ADD_HEADER (p, 8);
ADD_TRAILER (p, 8);
ADD_TRAILER (p, 8);
p.RemoveAtStart (8+10+8);
p->RemoveAtStart (8+10+8);
CHECK_HISTORY (p, 1, 8);
p = Packet (10);
p = Create<Packet> (10);
ADD_HEADER (p, 10);
ADD_HEADER (p, 8);
ADD_TRAILER (p, 6);
ADD_TRAILER (p, 7);
ADD_TRAILER (p, 9);
p.RemoveAtStart (5);
p.RemoveAtEnd (12);
p->RemoveAtStart (5);
p->RemoveAtEnd (12);
CHECK_HISTORY (p, 5, 3, 10, 10, 6, 4);
p = Packet (10);
p = Create<Packet> (10);
ADD_HEADER (p, 10);
ADD_TRAILER (p, 6);
p.RemoveAtEnd (18);
p->RemoveAtEnd (18);
ADD_TRAILER (p, 5);
ADD_HEADER (p, 3);
CHECK_HISTORY (p, 3, 3, 8, 5);
p.RemoveAtStart (12);
p->RemoveAtStart (12);
CHECK_HISTORY (p, 1, 4);
p.RemoveAtEnd (2);
p->RemoveAtEnd (2);
CHECK_HISTORY (p, 1, 2);
ADD_HEADER (p, 10);
CHECK_HISTORY (p, 2, 10, 2);
p.RemoveAtEnd (5);
p->RemoveAtEnd (5);
CHECK_HISTORY (p, 1, 7);
Packet p2 = Packet (0);
Packet p3 = Packet (0);
Ptr<Packet> p2 = Create<Packet> (0);
Ptr<Packet> p3 = Create<Packet> (0);
p = Packet (40);
p = Create<Packet> (40);
ADD_HEADER (p, 5);
ADD_HEADER (p, 8);
CHECK_HISTORY (p, 3, 8, 5, 40);
p1 = p.CreateFragment (0, 5);
p2 = p.CreateFragment (5, 5);
p3 = p.CreateFragment (10, 43);
p1 = p->CreateFragment (0, 5);
p2 = p->CreateFragment (5, 5);
p3 = p->CreateFragment (10, 43);
CHECK_HISTORY (p1, 1, 5);
CHECK_HISTORY (p2, 2, 3, 2);
CHECK_HISTORY (p3, 2, 3, 40);
p1.AddAtEnd (p2);
p1->AddAtEnd (p2);
CHECK_HISTORY (p1, 2, 8, 2);
CHECK_HISTORY (p2, 2, 3, 2);
p1.AddAtEnd (p3);
p1->AddAtEnd (p3);
CHECK_HISTORY (p1, 3, 8, 5, 40);
CHECK_HISTORY (p2, 2, 3, 2);
CHECK_HISTORY (p3, 2, 3, 40);
p1 = p.CreateFragment (0, 5);
p1 = p->CreateFragment (0, 5);
CHECK_HISTORY (p1, 1, 5);
p3 = Packet (50);
p3 = Create<Packet> (50);
ADD_HEADER (p3, 8);
CHECK_HISTORY (p3, 2, 8, 50);
CHECK_HISTORY (p1, 1, 5);
p1.AddAtEnd (p3);
p1->AddAtEnd (p3);
CHECK_HISTORY (p1, 3, 5, 8, 50);
ADD_HEADER (p1, 5);
CHECK_HISTORY (p1, 4, 5, 5, 8, 50);
@@ -613,71 +613,71 @@ PacketMetadataTest::RunTests (void)
CHECK_HISTORY (p1, 5, 5, 5, 8, 50, 2);
REM_HEADER (p1, 5);
CHECK_HISTORY (p1, 4, 5, 8, 50, 2);
p1.RemoveAtEnd (60);
p1->RemoveAtEnd (60);
CHECK_HISTORY (p1, 1, 5);
p1.AddAtEnd (p2);
p1->AddAtEnd (p2);
CHECK_HISTORY (p1, 2, 8, 2);
CHECK_HISTORY (p2, 2, 3, 2);
p3 = Packet (40);
p3 = Create<Packet> (40);
ADD_HEADER (p3, 5);
ADD_HEADER (p3, 5);
CHECK_HISTORY (p3, 3, 5, 5, 40);
p1 = p3.CreateFragment (0, 5);
p2 = p3.CreateFragment (5, 5);
p1 = p3->CreateFragment (0, 5);
p2 = p3->CreateFragment (5, 5);
CHECK_HISTORY (p1, 1, 5);
CHECK_HISTORY (p2, 1, 5);
p1.AddAtEnd (p2);
p1->AddAtEnd (p2);
CHECK_HISTORY (p1, 2, 5, 5);
p = Packet (0);
p = Create<Packet> (0);
CHECK_HISTORY (p, 0);
p3 = Packet (0);
p3 = Create<Packet> (0);
ADD_HEADER (p3, 5);
ADD_HEADER (p3, 5);
CHECK_HISTORY (p3, 2, 5, 5);
p1 = p3.CreateFragment (0, 4);
p2 = p3.CreateFragment (9, 1);
p1 = p3->CreateFragment (0, 4);
p2 = p3->CreateFragment (9, 1);
CHECK_HISTORY (p1, 1, 4);
CHECK_HISTORY (p2, 1, 1);
p1.AddAtEnd (p2);
p1->AddAtEnd (p2);
CHECK_HISTORY (p1, 2, 4, 1);
p = Packet (2000);
p = Create<Packet> (2000);
CHECK_HISTORY (p, 1, 2000);
p = Packet ();
p = Create<Packet> ();
ADD_TRAILER (p, 10);
ADD_HEADER (p, 5);
p1 = p.CreateFragment (0, 8);
p2 = p.CreateFragment (8, 7);
p1.AddAtEnd (p2);
p1 = p->CreateFragment (0, 8);
p2 = p->CreateFragment (8, 7);
p1->AddAtEnd (p2);
CHECK_HISTORY (p, 2, 5, 10);
p = Packet ();
p = Create<Packet> ();
ADD_TRAILER (p, 10);
REM_TRAILER (p, 10);
ADD_TRAILER (p, 10);
CHECK_HISTORY (p, 1, 10);
p = Packet ();
p = Create<Packet> ();
ADD_HEADER (p, 10);
REM_HEADER (p, 10);
ADD_HEADER (p, 10);
CHECK_HISTORY (p, 1, 10);
p = Packet ();
p = Create<Packet> ();
ADD_HEADER (p, 10);
p = DoAddHeader (p);
CHECK_HISTORY (p, 2, 10, 10);
p = Packet (10);
p = Create<Packet> (10);
ADD_HEADER (p, 8);
ADD_TRAILER (p, 8);
ADD_TRAILER (p, 8);
p.RemoveAtStart (8+10+8);
p->RemoveAtStart (8+10+8);
CHECK_HISTORY (p, 1, 8);
return ok;
+3 -3
View File
@@ -134,7 +134,7 @@ private:
struct Printer
{
uint32_t m_chunkUid;
Ptr<CallbackImplBase> m_printer;
CallbackBase m_printer;
Callback<void,std::ostream &,uint32_t,uint32_t,std::string &,
struct PacketPrinter::FragmentInformation> m_fragmentPrinter;
};
@@ -158,7 +158,7 @@ PacketPrinter::SetHeaderPrinter (Callback<void,std::ostream &,uint32_t,uint32_t,
{
Printer p;
p.m_chunkUid = T::GetUid ();
p.m_printer = printer.GetImpl ();
p.m_printer = printer;
p.m_fragmentPrinter = fragmentPrinter;
m_printerList.push_back (p);
}
@@ -170,7 +170,7 @@ PacketPrinter::SetTrailerPrinter (Callback<void,std::ostream &,uint32_t,uint32_t
{
Printer p;
p.m_chunkUid = T::GetUid ();
p.m_printer = printer.GetImpl ();
p.m_printer = printer;
p.m_fragmentPrinter = fragmentPrinter;
m_printerList.push_back (p);
}
+71 -18
View File
@@ -26,22 +26,72 @@ namespace ns3 {
uint32_t Packet::m_globalUid = 0;
void
Packet::Ref (void) const
{
m_refCount++;
}
void
Packet::Unref (void) const
{
m_refCount--;
if (m_refCount == 0)
{
delete this;
}
}
Ptr<Packet>
Packet::Copy (void) const
{
// we need to invoke the copy constructor directly
// rather than calling Create because the copy constructor
// is private.
return Ptr<Packet> (new Packet (*this), false);
}
Packet::Packet ()
: m_buffer (),
m_metadata (m_globalUid, 0)
m_tags (),
m_metadata (m_globalUid, 0),
m_refCount (1)
{
m_globalUid++;
}
Packet::Packet (const Packet &o)
: m_buffer (o.m_buffer),
m_tags (o.m_tags),
m_metadata (o.m_metadata),
m_refCount (1)
{}
Packet &
Packet::operator = (const Packet &o)
{
if (this == &o)
{
return *this;
}
m_buffer = o.m_buffer;
m_tags = o.m_tags;
m_metadata = o.m_metadata;
return *this;
}
Packet::Packet (uint32_t size)
: m_buffer (size),
m_metadata (m_globalUid, size)
m_tags (),
m_metadata (m_globalUid, size),
m_refCount (1)
{
m_globalUid++;
}
Packet::Packet (uint8_t const*buffer, uint32_t size)
: m_buffer (),
m_metadata (m_globalUid, size)
m_tags (),
m_metadata (m_globalUid, size),
m_refCount (1)
{
m_globalUid++;
m_buffer.AddAtStart (size);
@@ -52,17 +102,20 @@ Packet::Packet (uint8_t const*buffer, uint32_t size)
Packet::Packet (Buffer buffer, Tags tags, PacketMetadata metadata)
: m_buffer (buffer),
m_tags (tags),
m_metadata (metadata)
m_metadata (metadata),
m_refCount (1)
{}
Packet
Ptr<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);
// again, call the constructor directly rather than
// through Create because it is private.
return Ptr<Packet> (new Packet (buffer, m_tags, metadata), false);
}
uint32_t
@@ -72,9 +125,9 @@ Packet::GetSize (void) const
}
void
Packet::AddAtEnd (Packet packet)
Packet::AddAtEnd (Ptr<const Packet> packet)
{
Buffer src = packet.m_buffer.CreateFullCopy ();
Buffer src = packet->m_buffer.CreateFullCopy ();
Buffer dst = m_buffer.CreateFullCopy ();
dst.AddAtEnd (src.GetSize ());
@@ -86,7 +139,7 @@ Packet::AddAtEnd (Packet packet)
* XXX: we might need to merge the tag list of the
* other packet into the current packet.
*/
m_metadata.AddAtEnd (packet.m_metadata);
m_metadata.AddAtEnd (packet->m_metadata);
}
void
Packet::AddPaddingAtEnd (uint32_t size)
@@ -233,20 +286,20 @@ 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);
Ptr<Packet> pkt1 = Create<Packet> (reinterpret_cast<const uint8_t*> ("hello"), 5);
Ptr<Packet> pkt2 = Create<Packet> (reinterpret_cast<const uint8_t*> (" world"), 6);
Ptr<Packet> packet = Create<Packet> ();
packet->AddAtEnd (pkt1);
packet->AddAtEnd (pkt2);
if (packet.GetSize () != 11)
if (packet->GetSize () != 11)
{
Failure () << "expected size 11, got " << packet.GetSize () << std::endl;
Failure () << "expected size 11, got " << packet->GetSize () << std::endl;
ok = false;
}
std::string msg = std::string (reinterpret_cast<const char *>(packet.PeekData ()),
packet.GetSize ());
std::string msg = std::string (reinterpret_cast<const char *>(packet->PeekData ()),
packet->GetSize ());
if (msg != "hello world")
{
Failure () << "expected 'hello world', got '" << msg << "'" << std::endl;
+27 -5
View File
@@ -30,6 +30,7 @@
#include "tag.h"
#include "ns3/callback.h"
#include "ns3/assert.h"
#include "ns3/ptr.h"
namespace ns3 {
@@ -74,6 +75,11 @@ class PacketPrinter;
*/
class Packet {
public:
void Ref (void) const;
void Unref (void) const;
Ptr<Packet> Copy (void) const;
/**
* Create an empty packet with a new uid (as returned
* by getUid).
@@ -107,7 +113,7 @@ public:
* \param length length of fragment to create
* \returns a fragment of the original packet
*/
Packet CreateFragment (uint32_t start, uint32_t length) const;
Ptr<Packet> CreateFragment (uint32_t start, uint32_t length) const;
/**
* \returns the size in bytes of the packet (including the zero-filled
* initial payload)
@@ -152,15 +158,27 @@ public:
template <typename T>
uint32_t RemoveTrailer (T &trailer);
/**
* \param tag a pointer to the tag to attach to this packet.
*
* 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. The copy constructor of the
* tag is invoked to copy it into the tag buffer.
*
* \param tag a pointer to the tag to attach to this packet.
* Note that adding a tag is a const operation which is pretty
* un-intuitive. The rationale is that the content and behavior of
* a packet is _not_ changed when a tag is added to a packet: any
* code which was not aware of the new tag is going to work just
* the same if the new tag is added. The real reason why adding a
* tag was made a const operation is to allow a trace sink which gets
* a packet to tag the packet, even if the packet is const (and most
* trace sources should use const packets because it would be
* totally evil to allow a trace sink to modify the content of a
* packet).
*
*/
template <typename T>
void AddTag (T const &tag);
void AddTag (T const &tag) const;
/**
* Remove a tag from this packet. The data stored internally
* for this tag is copied in the input tag if an instance
@@ -210,7 +228,7 @@ public:
*
* \param packet packet to concatenate
*/
void AddAtEnd (Packet packet);
void AddAtEnd (Ptr<const Packet> packet);
/**
* \param size number of padding bytes to add.
*/
@@ -332,15 +350,19 @@ public:
void Deserialize (Buffer buffer);
private:
Packet (Buffer buffer, Tags tags, PacketMetadata metadata);
Packet (const Packet &o);
Packet &operator = (const Packet &o);
Buffer m_buffer;
Tags m_tags;
PacketMetadata m_metadata;
mutable uint32_t m_refCount;
static uint32_t m_globalUid;
};
std::ostream& operator<< (std::ostream& os, const Packet &packet);
/**
* \ingroup common
* \defgroup packetperf Packet Performance
* 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
@@ -441,7 +463,7 @@ Packet::RemoveTrailer (T &trailer)
template <typename T>
void Packet::AddTag (T const& tag)
void Packet::AddTag (T const& tag) const
{
const Tag *parent;
// if the following assignment fails, it is because the
+4 -4
View File
@@ -89,7 +89,7 @@ PcapWriter::WriteHeader (uint32_t network)
void
PcapWriter::WritePacket (Packet const packet)
PcapWriter::WritePacket (Ptr<const Packet> packet)
{
if (m_writer != 0)
{
@@ -98,9 +98,9 @@ PcapWriter::WritePacket (Packet const packet)
uint64_t us = current % 1000000;
Write32 (s & 0xffffffff);
Write32 (us & 0xffffffff);
Write32 (packet.GetSize ());
Write32 (packet.GetSize ());
WriteData (packet.PeekData (), packet.GetSize ());
Write32 (packet->GetSize ());
Write32 (packet->GetSize ());
WriteData (packet->PeekData (), packet->GetSize ());
}
}
+3 -2
View File
@@ -24,10 +24,11 @@
#include "ns3/callback.h"
#include <stdint.h>
#include "packet.h"
namespace ns3 {
class Packet;
/**
* \brief Pcap output for Packet logger
*
@@ -62,7 +63,7 @@ public:
/**
* \param packet packet to write to output file
*/
void WritePacket (Packet const packet);
void WritePacket (Ptr<const Packet> packet);
private:
void WriteData (uint8_t const*buffer, uint32_t size);
+4 -4
View File
@@ -30,7 +30,7 @@ struct Tags::TagData *Tags::gFree = 0;
uint32_t Tags::gN_free = 0;
struct Tags::TagData *
Tags::AllocData (void)
Tags::AllocData (void) const
{
struct Tags::TagData *retval;
if (gFree != 0)
@@ -47,7 +47,7 @@ Tags::AllocData (void)
}
void
Tags::FreeData (struct TagData *data)
Tags::FreeData (struct TagData *data) const
{
if (gN_free > 1000)
{
@@ -61,7 +61,7 @@ Tags::FreeData (struct TagData *data)
}
#else
struct Tags::TagData *
Tags::AllocData (void)
Tags::AllocData (void) const
{
struct Tags::TagData *retval;
retval = new struct Tags::TagData ();
@@ -69,7 +69,7 @@ Tags::AllocData (void)
}
void
Tags::FreeData (struct TagData *data)
Tags::FreeData (struct TagData *data) const
{
delete data;
}
+14 -6
View File
@@ -44,7 +44,7 @@ public:
inline ~Tags ();
template <typename T>
void Add (T const&tag);
void Add (T const&tag) const;
template <typename T>
bool Remove (T &tag);
@@ -71,8 +71,8 @@ private:
};
bool Remove (uint32_t id);
struct Tags::TagData *AllocData (void);
void FreeData (struct TagData *data);
struct Tags::TagData *AllocData (void) const;
void FreeData (struct TagData *data) const;
static struct Tags::TagData *gFree;
static uint32_t gN_free;
@@ -96,7 +96,7 @@ namespace ns3 {
template <typename T>
void
Tags::Add (T const&tag)
Tags::Add (T const&tag) const
{
const Tag *parent;
// if the following assignment fails, it is because the
@@ -116,7 +116,7 @@ Tags::Add (T const&tag)
void *buf = &newStart->m_data;
new (buf) T (tag);
newStart->m_next = m_next;
m_next = newStart;
const_cast<Tags *> (this)->m_next = newStart;
}
template <typename T>
@@ -128,7 +128,15 @@ Tags::Remove (T &tag)
// input to this function is not a subclass of the Tag class.
parent = &tag;
NS_ASSERT (sizeof (T) <= Tags::SIZE);
return Remove (T::GetUid ());
if (Peek (tag))
{
Remove (T::GetUid ());
return true;
}
else
{
return false;
}
}
template <typename T>
+102
View File
@@ -0,0 +1,102 @@
#include "delay-jitter-estimation.h"
#include "ns3/tag.h"
#include "ns3/simulator.h"
namespace {
class TimestampTag : public ns3::Tag
{
public:
TimestampTag ();
static uint32_t GetUid (void);
void Print (std::ostream &os) const;
void Serialize (ns3::Buffer::Iterator start) const;
uint32_t Deserialize (ns3::Buffer::Iterator start);
uint32_t GetSerializedSize (void) const;
ns3::Time GetTxTime (void) const;
private:
uint64_t m_creationTime;
};
TimestampTag::TimestampTag ()
: m_creationTime (ns3::Simulator::Now ().GetTimeStep ())
{}
uint32_t
TimestampTag::GetUid (void)
{
static uint32_t uid = ns3::Tag::AllocateUid<TimestampTag> ("mathieu.paper.TimestampTag");
return uid;
}
void
TimestampTag::Print (std::ostream &os) const
{
os << ns3::TimeStep (m_creationTime);
}
void
TimestampTag::Serialize (ns3::Buffer::Iterator start) const
{}
uint32_t
TimestampTag::Deserialize (ns3::Buffer::Iterator start)
{
return 0;
}
uint32_t
TimestampTag::GetSerializedSize (void) const
{
return 0;
}
ns3::Time
TimestampTag::GetTxTime (void) const
{
return ns3::TimeStep (m_creationTime);
}
}
namespace ns3 {
DelayJitterEstimation::DelayJitterEstimation ()
: m_previousRx (Simulator::Now ()),
m_previousRxTx (Simulator::Now ()),
m_jitter (Seconds (0.0)),
m_delay (Seconds (0.0))
{}
void
DelayJitterEstimation::PrepareTx (Ptr<const Packet> packet)
{
TimestampTag tag;
packet->AddTag (tag);
}
void
DelayJitterEstimation::RecordRx (Ptr<const Packet> packet)
{
TimestampTag tag;
bool found;
found = packet->PeekTag (tag);
if (!found)
{
return;
}
tag.GetTxTime ();
Time delta = (Simulator::Now () - m_previousRx) - (tag.GetTxTime () - m_previousRxTx);
m_jitter += (Abs (delta) - m_jitter ) / Scalar (16.0);
m_previousRx = Simulator::Now ();
m_previousRxTx = tag.GetTxTime ();
m_delay = Simulator::Now () - tag.GetTxTime ();
}
Time
DelayJitterEstimation::GetLastDelay (void) const
{
return m_delay;
}
Time
DelayJitterEstimation::GetLastJitter (void) const
{
return m_jitter;
}
} // namespace ns3
+59
View File
@@ -0,0 +1,59 @@
#ifndef DELAY_JITTER_ESTIMATION_H
#define DELAY_JITTER_ESTIMATION_H
#include "ns3/nstime.h"
#include "ns3/packet.h"
namespace ns3 {
/**
* \brief quick and diry delay and jitter estimation
*
*/
class DelayJitterEstimation
{
public:
DelayJitterEstimation ();
/**
* \param packet the packet to send over a wire
*
* This method should be invoked once on each packet to
* record within the packet the tx time which is used upon
* packet reception to calculate the delay and jitter. The
* tx time is stored in the packet as an ns3::Tag which means
* that it does not use any network ressources and is not
* taken into account in transmission delay calculations.
*/
static void PrepareTx (Ptr<const Packet> packet);
/**
* \param packet the packet received
*
* Invoke this method to update the delay and jitter calculations
* After a call to this method, \ref GetLastDelay and \ref GetLastJitter
* will return an updated delay and jitter.
*/
void RecordRx (Ptr<const Packet> packet);
/**
* \returns the updated delay.
*/
Time GetLastDelay (void) const;
/**
* The jitter is calculated using the RFC 1889 (RTP) jitter
* definition.
*
* \returns the updated jitter.
*/
Time GetLastJitter (void) const;
private:
Time m_previousRx;
Time m_previousRxTx;
Time m_jitter;
Time m_delay;
};
} // namespace ns3
#endif /* DELAY_JITTER_ESTIMATION_H */
+186
View File
@@ -0,0 +1,186 @@
/* -*- 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 "gnuplot.h"
#include "ns3/assert.h"
#include <ostream>
namespace ns3 {
GnuplotDataset::GnuplotDataset (std::string title)
: m_title (title),
m_style (LINES),
m_errorBars (NONE)
{}
void
GnuplotDataset::SetStyle (enum Style style)
{
m_style = style;
}
void
GnuplotDataset::SetErrorBars (enum ErrorBars errorBars)
{
m_errorBars = errorBars;
}
void
GnuplotDataset::Add (double x, double y)
{
NS_ASSERT (m_errorBars == NONE);
struct Data data;
data.x = x;
data.y = y;
data.dx = 0.0;
data.dy = 0.0;
m_dataset.push_back (data);
}
void
GnuplotDataset::Add (double x, double y, double errorDelta)
{
NS_ASSERT (m_errorBars == X || m_errorBars == Y);
struct Data data;
data.x = x;
data.y = y;
data.dx = errorDelta;
data.dy = errorDelta;
m_dataset.push_back (data);
}
Gnuplot::Gnuplot (std::string pngFilename)
: m_pngFilename (pngFilename)
{}
Gnuplot::~Gnuplot ()
{
for (Datasets::const_iterator i = m_datasets.begin (); i != m_datasets.end (); i++)
{
delete *i;
}
m_datasets.clear ();
}
void
Gnuplot::SetLegend (std::string xLegend, std::string yLegend)
{
m_xLegend = xLegend;
m_yLegend = yLegend;
}
void
Gnuplot::AddDataset (const GnuplotDataset &dataset)
{
m_datasets.push_back (new GnuplotDataset (dataset));
}
void
Gnuplot::GenerateOutput (std::ostream &os)
{
os << "set terminal png" << std::endl;
os << "set output '" << m_pngFilename << "'" << std::endl;
os << "set xlabel '" << m_xLegend << "'" << std::endl;
os << "set ylabel '" << m_yLegend << "'" << std::endl;
os << "plot ";
for (Datasets::const_iterator i = m_datasets.begin (); i != m_datasets.end ();)
{
os << "'-' title '" << (*i)->m_title << "'";
switch ((*i)->m_style) {
case GnuplotDataset::LINES:
os << " with lines";
break;
case GnuplotDataset::POINTS:
switch ((*i)->m_errorBars)
{
case GnuplotDataset::NONE:
os << " with points";
break;
case GnuplotDataset::X:
os << " with xerrorbars";
break;
case GnuplotDataset::Y:
os << " with yerrorbars";
break;
case GnuplotDataset::XY:
os << " with xyerrorbars";
break;
}
break;
case GnuplotDataset::LINES_POINTS:
switch ((*i)->m_errorBars)
{
case GnuplotDataset::NONE:
os << " with linespoints";
break;
case GnuplotDataset::X:
os << " with xerrorlines";
break;
case GnuplotDataset::Y:
os << " with yerrorlines";
break;
case GnuplotDataset::XY:
os << " with xyerrorlines";
break;
}
break;
case GnuplotDataset::DOTS:
os << " with dots";
break;
case GnuplotDataset::IMPULSES:
os << " with impulses";
break;
case GnuplotDataset::STEPS:
os << " with steps";
break;
case GnuplotDataset::FSTEPS:
os << " with fsteps";
break;
case GnuplotDataset::HISTEPS:
os << " with histeps";
break;
}
i++;
if (i != m_datasets.end ())
{
os << ", ";
}
}
os << std::endl;
for (Datasets::const_iterator i = m_datasets.begin (); i != m_datasets.end (); i++)
{
for (GnuplotDataset::Dataset::const_iterator j = (*i)->m_dataset.begin ();
j != (*i)->m_dataset.end (); j++)
{
switch ((*i)->m_errorBars) {
case GnuplotDataset::NONE:
os << j->x << " " << j->y << std::endl;
break;
case GnuplotDataset::X:
os << j->x << " " << j->y << " " << j->dx << std::endl;
break;
case GnuplotDataset::Y:
os << j->x << " " << j->y << " " << j->dy << std::endl;
break;
case GnuplotDataset::XY:
os << j->x << " " << j->y << " " << j->dx << " " << j->dy << std::endl;
break;
}
}
os << "e" << std::endl;
}
}
} // namespace ns3
+91
View File
@@ -0,0 +1,91 @@
/* -*- 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 GNUPLOT_H
#define GNUPLOT_H
#include <string>
#include <vector>
#include <utility>
namespace ns3 {
class GnuplotDataset
{
public:
enum Style {
LINES,
POINTS,
LINES_POINTS,
DOTS,
IMPULSES,
STEPS,
FSTEPS,
HISTEPS,
};
enum ErrorBars {
NONE,
X,
Y,
XY
};
GnuplotDataset (std::string title);
void SetStyle (enum Style style);
void SetErrorBars (enum ErrorBars errorBars);
void Add (double x, double y);
void Add (double x, double y, double errorDelta);
void Add (double x, double y, double errorDeltaX, double errorDeltaY);
private:
friend class Gnuplot;
struct Data {
double x;
double y;
double dx;
double dy;
};
typedef std::vector<struct Data> Dataset;
Dataset m_dataset;
std::string m_title;
enum Style m_style;
enum ErrorBars m_errorBars;
};
class Gnuplot
{
public:
Gnuplot (std::string pngFilename);
~Gnuplot ();
void SetLegend (std::string xLegend, std::string yLegend);
void AddDataset (const GnuplotDataset &dataset);
void GenerateOutput (std::ostream &os);
private:
typedef std::vector<GnuplotDataset *> Datasets;
Datasets m_datasets;
std::string m_xLegend;
std::string m_yLegend;
std::string m_pngFilename;
};
} // namespace ns3
#endif /* GNUPLOT_H */
+16
View File
@@ -0,0 +1,16 @@
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
def build(bld):
module = bld.create_ns3_module('contrib', ['simulator'])
module.source = [
'event-garbage-collector.cc',
'gnuplot.cc',
'delay-jitter-estimation.cc',
]
headers = bld.create_obj('ns3header')
headers.source = [
'event-garbage-collector.h',
'gnuplot.h',
'delay-jitter-estimation.h',
]
+306
View File
@@ -0,0 +1,306 @@
/* -*- 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 "array-trace-resolver.h"
namespace ns3 {
ArrayTraceResolverMatcher::ArrayTraceResolverMatcher (std::string element)
: m_element (element)
{}
bool
ArrayTraceResolverMatcher::Matches (uint32_t i) const
{
if (m_element == "*")
{
return true;
}
std::string::size_type tmp;
tmp = m_element.find ("|");
if (tmp != std::string::npos)
{
std::string left = m_element.substr (0, tmp-0);
std::string right = m_element.substr (tmp+1, m_element.size () - (tmp + 1));
ArrayTraceResolverMatcher matcher = ArrayTraceResolverMatcher (left);
if (matcher.Matches (i))
{
return true;
}
matcher = ArrayTraceResolverMatcher (right);
if (matcher.Matches (i))
{
return true;
}
return false;
}
std::string::size_type leftBracket = m_element.find ("[");
std::string::size_type rightBracket = m_element.find ("]");
std::string::size_type dash = m_element.find ("-");
if (leftBracket == 0 && rightBracket == m_element.size () - 1 &&
dash > leftBracket && dash < rightBracket)
{
std::string lowerBound = m_element.substr (leftBracket + 1, dash - (leftBracket + 1));
std::string upperBound = m_element.substr (dash + 1, rightBracket - (dash + 1));
uint32_t min;
uint32_t max;
if (StringToUint32 (lowerBound, &min) &&
StringToUint32 (upperBound, &max) &&
i >= min && i <= max)
{
return true;
}
else
{
return false;
}
}
uint32_t value;
if (StringToUint32 (m_element, &value) &&
i == value)
{
return true;
}
return false;
}
bool
ArrayTraceResolverMatcher::StringToUint32 (std::string str, uint32_t *value) const
{
std::istringstream iss;
iss.str (str);
iss >> (*value);
return !iss.bad () && !iss.fail ();
}
}//namespace ns3
#ifdef RUN_SELF_TESTS
#include <stdarg.h>
#include "test.h"
#include "object.h"
#include "array-trace-resolver.h"
#include "callback-trace-source.h"
#include "composite-trace-resolver.h"
namespace ns3 {
class ObjectTraceTesterIndex : public TraceContextElement
{
public:
ObjectTraceTesterIndex ();
ObjectTraceTesterIndex (uint32_t index);
void Print (std::ostream &os);
static uint16_t GetUid (void);
uint32_t Get (void) const;
std::string GetTypeName (void) const;
private:
uint32_t m_index;
};
ObjectTraceTesterIndex::ObjectTraceTesterIndex ()
: m_index (0)
{}
ObjectTraceTesterIndex::ObjectTraceTesterIndex (uint32_t index)
: m_index (index)
{}
void
ObjectTraceTesterIndex::Print (std::ostream &os)
{
os << "nodeid=" << m_index;
}
uint16_t
ObjectTraceTesterIndex::GetUid (void)
{
static uint16_t uid = AllocateUid<ObjectTraceTesterIndex> ("ObjectTraceTesterIndex");
return uid;
}
uint32_t
ObjectTraceTesterIndex::Get (void) const
{
return m_index;
}
std::string
ObjectTraceTesterIndex::GetTypeName (void) const
{
return "ns3::ObjectTraceTesterIndex";
}
class ObjectTraceTester : public Object
{
public:
void Do (uint32_t i);
protected:
virtual Ptr<TraceResolver> GetTraceResolver (void) const;
private:
CallbackTraceSource<uint32_t> m_test;
};
void
ObjectTraceTester::Do (uint32_t i)
{
m_test (i);
}
Ptr<TraceResolver>
ObjectTraceTester::GetTraceResolver (void) const
{
Ptr<CompositeTraceResolver> resolver = Create<CompositeTraceResolver> ();
resolver->AddSource ("test",
TraceDoc ("Test"),
m_test);
resolver->SetParentResolver (Object::GetTraceResolver ());
return resolver;
}
class ArrayTraceResolverTest : public Test
{
public:
ArrayTraceResolverTest ();
virtual bool RunTests (void);
private:
bool RunOne (uint32_t n, std::string str,
uint32_t nExpected, ...);
void OneItem (const TraceContext &context,
uint32_t i);
typedef std::vector<uint32_t> Got;
Got m_got;
};
ArrayTraceResolverTest::ArrayTraceResolverTest ()
: Test ("ArrayTraceResolver")
{}
bool
ArrayTraceResolverTest::RunOne (uint32_t n, std::string str,
uint32_t nExpected, ...)
{
bool result = true;
std::vector<uint32_t> expected;
va_list ap;
va_start (ap, nExpected);
for (uint32_t k = 0; k < nExpected; k++)
{
uint32_t v = va_arg (ap, uint32_t);
expected.push_back (v);
}
va_end (ap);
std::sort (expected.begin (), expected.end ());
std::sort (m_got.begin (), m_got.end ());
std::vector<Ptr<ObjectTraceTester> > vec;
for (uint32_t i = 0; i < n; i++)
{
vec.push_back (CreateObject<ObjectTraceTester> ());
}
ArrayTraceResolver<ObjectTraceTesterIndex> resolver;
resolver.SetIterators (vec.begin (), vec.end ());
TraceContext context;
resolver.Connect (str, MakeCallback (&ArrayTraceResolverTest::OneItem, this), context);
uint32_t l = 0;
for (std::vector<Ptr<ObjectTraceTester> >::const_iterator j = vec.begin (); j != vec.end (); j++)
{
(*j)->Do (l);
l++;
}
NS_TEST_ASSERT_EQUAL (m_got.size (), expected.size ());
for (uint32_t m = 0; m < expected.size (); m++)
{
NS_TEST_ASSERT_EQUAL (m_got[m], expected[m]);
}
m_got.clear ();
resolver.Disconnect (str, MakeCallback (&ArrayTraceResolverTest::OneItem, this));
for (std::vector<Ptr<ObjectTraceTester> >::const_iterator j = vec.begin (); j != vec.end (); j++)
{
(*j)->Do (l);
l++;
}
NS_TEST_ASSERT_EQUAL (m_got.size (), 0);
m_got.clear ();
return result;
}
void
ArrayTraceResolverTest::OneItem (const TraceContext &context,
uint32_t i)
{
ObjectTraceTesterIndex index;
bool found = context.GetElement (index);
if (!found)
{
return;
}
if (index.Get () != i)
{
return;
}
m_got.push_back (i);
}
bool
ArrayTraceResolverTest::RunTests (void)
{
bool result = true;
NS_TEST_ASSERT (RunOne (0, "/*/test", 0));
NS_TEST_ASSERT (RunOne (1, "/*/test", 1, 0));
NS_TEST_ASSERT (RunOne (1, "/0/test", 1, 0));
NS_TEST_ASSERT (RunOne (1, "/[0-0]/test", 1, 0));
NS_TEST_ASSERT (RunOne (1, "/0|0/test", 1, 0));
NS_TEST_ASSERT (RunOne (2, "/*/test", 2, 0, 1));
NS_TEST_ASSERT (RunOne (2, "/0|1/test", 2, 0, 1));
NS_TEST_ASSERT (RunOne (2, "/1/test", 1, 1));
NS_TEST_ASSERT (RunOne (2, "/|1|/test", 1, 1));
NS_TEST_ASSERT (RunOne (2, "/0/test", 1, 0));
NS_TEST_ASSERT (RunOne (2, "/0|/test", 1, 0));
NS_TEST_ASSERT (RunOne (2, "/|0/test", 1, 0));
NS_TEST_ASSERT (RunOne (2, "/[0-1]/test", 2, 0, 1));
NS_TEST_ASSERT (RunOne (2, "/[0-0]/test", 1, 0));
NS_TEST_ASSERT (RunOne (2, "/[1-1]/test", 1, 1));
NS_TEST_ASSERT (RunOne (2, "/0|[1-1]/test", 2, 0, 1));
NS_TEST_ASSERT (RunOne (3, "/1|0/test", 2, 0, 1));
NS_TEST_ASSERT (RunOne (3, "/2|0/test", 2, 0, 2));
NS_TEST_ASSERT (RunOne (3, "/2|1/test", 2, 1, 2));
NS_TEST_ASSERT (RunOne (3, "/[0-1]/test", 2, 0, 1));
NS_TEST_ASSERT (RunOne (3, "/[1-2]/test", 2, 1, 2));
NS_TEST_ASSERT (RunOne (3, "/[0-2]/test", 3, 0, 1, 2));
NS_TEST_ASSERT (RunOne (3, "/[1-2]|0/test", 3, 0, 1, 2));
NS_TEST_ASSERT (RunOne (3, "/[1-1]|0|[2-2]/test", 3, 0, 1, 2));
NS_TEST_ASSERT (RunOne (3, "/[1-2]||/test", 2, 1, 2));
NS_TEST_ASSERT (RunOne (3, "/[1-2]||/test", 2, 2, 1));
NS_TEST_ASSERT (RunOne (3, "/||||/test", 0));
NS_TEST_ASSERT (RunOne (20, "/[5-10]|[2-3]|[15-17]/test", 11, 2, 3, 5, 6, 7, 8, 9, 10, 15, 16, 17));
NS_TEST_ASSERT (RunOne (3, "/[1-2]|[0-1]/test", 3, 0, 1, 2));
return result;
}
static ArrayTraceResolverTest g_arrayTraceResolverTest;
} // namespace ns3
#endif /* RUN_SELF_TESTS */
+37 -21
View File
@@ -23,6 +23,7 @@
#include <stdint.h>
#include <string>
#include <sstream>
#include "callback.h"
#include "trace-resolver.h"
#include "object.h"
@@ -78,6 +79,17 @@ private:
};
IteratorBase *m_iter;
};
class ArrayTraceResolverMatcher
{
public:
ArrayTraceResolverMatcher (std::string element);
bool Matches (uint32_t i) const;
bool StringToUint32 (std::string str, uint32_t *value) const;
private:
std::string m_element;
};
}//namespace ns3
@@ -133,19 +145,20 @@ ArrayTraceResolver<INDEX>::Connect (std::string path, CallbackBase const &cb, co
}
std::string id = GetElement (path);
std::string subpath = GetSubpath (path);
if (id == "*")
{
uint32_t j = 0;
for (m_iter->Rewind (); m_iter->HasNext (); m_iter->Next ())
{
TraceContext tmp = context;
INDEX index = j;
tmp.AddElement (index);
Ptr<Object> obj = m_iter->Get ();
obj->GetTraceResolver ()->Connect (subpath, cb, tmp);
j++;
}
}
ArrayTraceResolverMatcher matcher = ArrayTraceResolverMatcher (id);
uint32_t i = 0;
for (m_iter->Rewind (); m_iter->HasNext (); m_iter->Next ())
{
if (matcher.Matches (i))
{
TraceContext tmp = context;
INDEX index = i;
tmp.AddElement (index);
Ptr<Object> obj = m_iter->Get ();
obj->GetTraceResolver ()->Connect (subpath, cb, tmp);
}
i++;
}
}
template <typename INDEX>
void
@@ -157,14 +170,17 @@ ArrayTraceResolver<INDEX>::Disconnect (std::string path, CallbackBase const &cb)
}
std::string id = GetElement (path);
std::string subpath = GetSubpath (path);
if (id == "*")
{
for (m_iter->Rewind (); m_iter->HasNext (); m_iter->Next ())
{
Ptr<Object> obj = m_iter->Get ();
obj->TraceDisconnect (subpath, cb);
}
}
ArrayTraceResolverMatcher matcher = ArrayTraceResolverMatcher (id);
uint32_t i = 0;
for (m_iter->Rewind (); m_iter->HasNext (); m_iter->Next ())
{
if (matcher.Matches (i))
{
Ptr<Object> obj = m_iter->Get ();
obj->TraceDisconnect (subpath, cb);
}
i++;
}
}
template <typename INDEX>
void
+1
View File
@@ -28,6 +28,7 @@
#include "breakpoint.h"
/**
* \ingroup core
* \defgroup assert Assert
* \brief assert functions and macros
*
+23 -3
View File
@@ -72,7 +72,20 @@ void TestFRFour (int &, int &, int &, int &) {}
void TestFRFive (int &, int &, int &, int &, int &) {}
void TestFRSix (int &, int &, int &, int &, int &, int &) {}
class CallbackTest : public ns3::Test {
class X : public ns3::Test
{
public:
X () : Test ("Callback") {}
void PublicParent (void) {}
protected:
static void StaticProtectedParent (void) {}
void ProtectedParent (void) {}
private:
void PrivateParent (void) {}
};
class CallbackTest : public X
{
private:
bool m_test1;
bool m_test2;
@@ -107,8 +120,7 @@ public:
};
CallbackTest::CallbackTest ()
: ns3::Test ("Callback"),
m_test1 (false),
: m_test1 (false),
m_test2 (false),
m_test3 (false),
m_test4 (false)
@@ -294,6 +306,14 @@ CallbackTest::RunTests (void)
MakeBoundCallback (&TestFRFive, 1);
MakeCallback (&X::StaticProtectedParent);
MakeCallback (&X::PublicParent, this);
MakeCallback (&CallbackTest::ProtectedParent, this);
// as expected, fails.
//MakeCallback (&X::PrivateParent, this);
// unexpected, but fails too.
// It does fumble me.
//MakeCallback (&X::ProtectedParent, this);
return ok;
}
+47 -53
View File
@@ -75,18 +75,18 @@ public:
CallbackImplBase ()
: m_count (1) {}
virtual ~CallbackImplBase () {}
void Ref (void) {
void Ref (void) const {
m_count++;
}
void Unref (void) {
void Unref (void) const {
m_count--;
if (m_count == 0) {
delete this;
}
}
virtual bool IsEqual (CallbackImplBase const *other) const = 0;
virtual bool IsEqual (Ptr<const CallbackImplBase> other) const = 0;
private:
uint32_t m_count;
mutable uint32_t m_count;
};
// declare the CallbackImpl class
@@ -171,9 +171,9 @@ public:
R operator() (T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6) {
return m_functor (a1,a2,a3,a4,a5,a6);
}
virtual bool IsEqual (CallbackImplBase const *other) const {
virtual bool IsEqual (Ptr<const CallbackImplBase> other) const {
FunctorCallbackImpl<T,R,T1,T2,T3,T4,T5,T6> const *otherDerived =
dynamic_cast<FunctorCallbackImpl<T,R,T1,T2,T3,T4,T5,T6> const *> (other);
dynamic_cast<FunctorCallbackImpl<T,R,T1,T2,T3,T4,T5,T6> const *> (PeekPointer(other));
if (otherDerived == 0)
{
return false;
@@ -216,9 +216,9 @@ public:
R operator() (T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6) {
return ((CallbackTraits<OBJ_PTR>::GetReference (m_objPtr)).*m_memPtr) (a1, a2, a3, a4, a5, a6);
}
virtual bool IsEqual (CallbackImplBase const *other) const {
virtual bool IsEqual (Ptr<const CallbackImplBase> other) const {
MemPtrCallbackImpl<OBJ_PTR,MEM_PTR,R,T1,T2,T3,T4,T5,T6> const *otherDerived =
dynamic_cast<MemPtrCallbackImpl<OBJ_PTR,MEM_PTR,R,T1,T2,T3,T4,T5,T6> const *> (other);
dynamic_cast<MemPtrCallbackImpl<OBJ_PTR,MEM_PTR,R,T1,T2,T3,T4,T5,T6> const *> (PeekPointer (other));
if (otherDerived == 0)
{
return false;
@@ -237,9 +237,11 @@ private:
class CallbackBase {
public:
virtual ~CallbackBase () {}
virtual CallbackImplBase *PeekImpl (void) const = 0;
virtual Ptr<CallbackImplBase> GetImpl (void) const = 0;
CallbackBase () : m_impl () {}
Ptr<CallbackImplBase> GetImpl (void) const {return m_impl;}
protected:
CallbackBase (Ptr<CallbackImplBase> impl) : m_impl (impl) {}
Ptr<CallbackImplBase> m_impl;
};
/**
@@ -277,59 +279,69 @@ template<typename R,
typename T5 = empty, typename T6 = empty>
class Callback : public CallbackBase {
public:
Callback () {}
// 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,T6> > (functor))
: CallbackBase (Create<FunctorCallbackImpl<FUNCTOR,R,T1,T2,T3,T4,T5,T6> > (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,T6> > (objPtr, mem_ptr))
: CallbackBase (Create<MemPtrCallbackImpl<OBJ_PTR,MEM_PTR,R,T1,T2,T3,T4,T5,T6> > (objPtr, mem_ptr))
{}
Callback (Ptr<CallbackImpl<R,T1,T2,T3,T4,T5,T6> > const &impl)
: m_impl (impl)
: CallbackBase (impl)
{}
bool IsNull (void) const {
return (PeekImpl () == 0)?true:false;
return (DoPeekImpl () == 0)?true:false;
}
void Nullify (void) {
m_impl = 0;
}
Callback () : m_impl () {}
R operator() (void) const {
return (*(PeekImpl ())) ();
return (*(DoPeekImpl ())) ();
}
R operator() (T1 a1) const {
return (*(PeekImpl ())) (a1);
return (*(DoPeekImpl ())) (a1);
}
R operator() (T1 a1, T2 a2) const {
return (*(PeekImpl ())) (a1,a2);
return (*(DoPeekImpl ())) (a1,a2);
}
R operator() (T1 a1, T2 a2, T3 a3) const {
return (*(PeekImpl ())) (a1,a2,a3);
return (*(DoPeekImpl ())) (a1,a2,a3);
}
R operator() (T1 a1, T2 a2, T3 a3, T4 a4) const {
return (*(PeekImpl ())) (a1,a2,a3,a4);
return (*(DoPeekImpl ())) (a1,a2,a3,a4);
}
R operator() (T1 a1, T2 a2, T3 a3, T4 a4,T5 a5) const {
return (*(PeekImpl ())) (a1,a2,a3,a4,a5);
return (*(DoPeekImpl ())) (a1,a2,a3,a4,a5);
}
R operator() (T1 a1, T2 a2, T3 a3, T4 a4,T5 a5,T6 a6) const {
return (*(PeekImpl ())) (a1,a2,a3,a4,a5,a6);
return (*(DoPeekImpl ())) (a1,a2,a3,a4,a5,a6);
}
bool IsEqual (CallbackBase const &other) const {
return PeekImpl ()->IsEqual (other.PeekImpl ());
bool IsEqual (const CallbackBase &other) const {
return m_impl->IsEqual (other.GetImpl ());
}
bool CheckType (CallbackBase const& other) const {
CallbackImplBase *otherBase = other.PeekImpl ();
if (dynamic_cast<CallbackImpl<R,T1,T2,T3,T4,T5,T6> *> (otherBase) != 0)
bool CheckType (const CallbackBase & other) const {
return DoCheckType (other.GetImpl ());
}
void Assign (const CallbackBase &other) {
DoAssign (other.GetImpl ());
}
private:
CallbackImpl<R,T1,T2,T3,T4,T5,T6> *DoPeekImpl (void) const {
return static_cast<CallbackImpl<R,T1,T2,T3,T4,T5,T6> *> (PeekPointer (m_impl));
}
bool DoCheckType (Ptr<const CallbackImplBase> other) const {
if (dynamic_cast<const CallbackImpl<R,T1,T2,T3,T4,T5,T6> *> (PeekPointer (other)) != 0)
{
return true;
}
@@ -338,37 +350,19 @@ public:
return false;
}
}
void Assign (CallbackBase const &other) {
if (!CheckType (other))
void DoAssign (Ptr<const CallbackImplBase> other) {
if (!DoCheckType (other))
{
NS_FATAL_ERROR ("Incompatible types. (feed to \"c++filt -t\")"
" got=" << typeid (other).name () <<
" got=" << typeid (*other).name () <<
", expected=" << typeid (*this).name ());
}
const Callback<R, T1,T2,T3,T4,T5,T6> *goodType = static_cast<const Callback<R,T1,T2,T3,T4,T5,T6> *> (&other);
*this = *goodType;
m_impl = const_cast<CallbackImplBase *> (PeekPointer (other));
}
void Assign (Ptr<CallbackImplBase> other) {
CallbackImpl<R,T1,T2,T3,T4,T5,T6> *impl = dynamic_cast<CallbackImpl<R,T1,T2,T3,T4,T5,T6> *> (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,T6> (impl);
}
virtual Ptr<CallbackImplBase>GetImpl (void) const {
return m_impl;
}
private:
virtual CallbackImpl<R,T1,T2,T3,T4,T5,T6> *PeekImpl (void) const {
return PeekPointer (m_impl);
}
Ptr<CallbackImpl<R,T1,T2,T3,T4,T5,T6> > m_impl;
};
/**
* \ingroup core
* \defgroup MakeCallback MakeCallback
*
*/
@@ -675,9 +669,9 @@ public:
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 {
virtual bool IsEqual (Ptr<const CallbackImplBase> 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);
dynamic_cast<BoundFunctorCallbackImpl<T,R,TX,T1,T2,T3,T4,T5> const *> (PeekPointer (other));
if (otherDerived == 0)
{
return false;
+8 -8
View File
@@ -188,45 +188,45 @@ public:
std::ostringstream nullout;
std::streambuf *origcerr = std::cerr.rdbuf (nullout.rdbuf ());
{
char *argv[] = {"run-tests", "--loops", "bad-value", NULL};
const char *argv[] = {"run-tests", "--loops", "bad-value", NULL};
int argc = sizeof (argv) / sizeof (argv[0]) - 1;
uint32_t loops = 123;
CommandLine::AddArgValue ("loops","a test of the command line", loops);
CommandLine::Parse (argc, argv);
CommandLine::Parse (argc, const_cast<char **> (argv));
NS_TEST_ASSERT_EQUAL (loops, 123);
}
{
char *argv[] = {"run-tests", "--loops=bad-value", NULL};
const char *argv[] = {"run-tests", "--loops=bad-value", NULL};
int argc = sizeof (argv) / sizeof (argv[0]) - 1;
uint32_t loops = 123;
CommandLine::AddArgValue ("loops","a test of the command line", loops);
CommandLine::Parse (argc, argv);
CommandLine::Parse (argc, const_cast<char **> (argv));
NS_TEST_ASSERT_EQUAL (loops, 123);
}
{
char *argv[] = {"run-tests", "--loops", "456", NULL};
const char *argv[] = {"run-tests", "--loops", "456", NULL};
int argc = sizeof (argv) / sizeof (argv[0]) - 1;
uint32_t loops = 123;
CommandLine::AddArgValue ("loops","a test of the command line", loops);
CommandLine::Parse (argc, argv);
CommandLine::Parse (argc, const_cast<char **> (argv));
NS_TEST_ASSERT_EQUAL (loops, 456);
}
{
char *argv[] = {"run-tests", "--loops=456", NULL};
const char *argv[] = {"run-tests", "--loops=456", NULL};
int argc = sizeof (argv) / sizeof (argv[0]) - 1;
uint32_t loops = 123;
CommandLine::AddArgValue ("loops","a test of the command line", loops);
CommandLine::Parse (argc, argv);
CommandLine::Parse (argc, const_cast<char **> (argv));
NS_TEST_ASSERT_EQUAL (loops, 456);
}
-402
View File
@@ -1,402 +0,0 @@
/* -*- 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
@@ -1,686 +0,0 @@
/* -*- 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 a5);
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 */
+1
View File
@@ -25,6 +25,7 @@
#include "callback.h"
/**
* \ingroup core
* \defgroup config Simulation configuration
*
*/
+1
View File
@@ -25,6 +25,7 @@
#include <iostream>
/**
* \ingroup core
* \defgroup error Error
* \brief fatal error handling
*
+37 -23
View File
@@ -39,6 +39,12 @@ namespace ns3 {
typedef std::list<std::pair <std::string, LogComponent *> > ComponentList;
typedef std::list<std::pair <std::string, LogComponent *> >::iterator ComponentListI;
static class PrintList
{
public:
PrintList ();
} g_printList;
static
ComponentList *GetComponentList (void)
{
@@ -46,6 +52,35 @@ ComponentList *GetComponentList (void)
return &components;
}
PrintList::PrintList ()
{
#ifdef HAVE_GETENV
char *envVar = getenv("NS_LOG");
if (envVar == 0)
{
return;
}
std::string env = envVar;
std::string::size_type cur = 0;
std::string::size_type next = 0;
while (next != std::string::npos)
{
next = env.find_first_of (";", cur);
std::string tmp = std::string (env, cur, next-cur);
if (tmp == "print-list")
{
LogComponentPrintList ();
exit (0);
break;
}
cur = next + 1;
}
#endif
}
LogComponent::LogComponent (char const * name)
: m_levels (0), m_name (name)
{
@@ -75,23 +110,10 @@ LogComponent::EnvVarCheck (char const * name)
std::string::size_type cur = 0;
std::string::size_type next = 0;
while (true)
while (next != std::string::npos)
{
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;
}
std::string tmp = std::string (env, cur, next-cur);
std::string::size_type equal = tmp.find ("=");
std::string component;
if (equal == std::string::npos)
@@ -189,15 +211,7 @@ LogComponent::EnvVarCheck (char const * name)
Enable ((enum LogLevel)level);
}
}
if (next == std::string::npos)
{
break;
}
cur = next + 1;
if (cur >= env.size ())
{
break;
}
}
#endif
}
+5 -4
View File
@@ -25,6 +25,7 @@
#include <iostream>
/**
* \ingroup core
* \defgroup logging Logging
* \brief Logging functions and macros
*
@@ -116,6 +117,9 @@ public:
switch (m_itemNumber)
{
case 0: // first item is actually the function name
std::clog << param << " (";
break;
case 1: // first parameter
if (m_parameterName)
{
std::clog << m_parameterName << "=" << param;
@@ -126,7 +130,7 @@ public:
std::clog << param;
}
break;
case 1:
default: // parameter following a previous parameter
if (m_parameterName)
{
std::clog << ", " << m_parameterName << "=" << param;
@@ -137,9 +141,6 @@ public:
std::clog << ", " << param;
}
break;
default: // parameter following a previous parameter
std::clog << ", " << param;
break;
}
m_itemNumber++;
return *this;
+347 -139
View File
@@ -21,49 +21,177 @@
#include "object.h"
#include "assert.h"
#include "singleton.h"
#include "uid-manager.h"
#include "trace-resolver.h"
#include "log.h"
#include <vector>
NS_LOG_COMPONENT_DEFINE ("Object");
/*********************************************************************
* Helper code
*********************************************************************/
namespace {
class IidManager : public ns3::UidManager
{};
class IidTree
class IidManager
{
public:
void SetParent (uint16_t child, const uint16_t *parent);
uint16_t LookupParent (uint16_t child);
uint16_t AllocateUid (std::string name);
void SetParent (uint16_t uid, uint16_t parent);
void AddConstructor (uint16_t uid, ns3::CallbackBase callback, uint32_t nArguments);
uint16_t GetUid (std::string name) const;
std::string GetName (uint16_t uid) const;
uint16_t GetParent (uint16_t uid) const;
ns3::CallbackBase GetConstructor (uint16_t uid, uint32_t nArguments);
bool HasConstructor (uint16_t uid);
uint32_t GetRegisteredN (void);
uint16_t GetRegistered (uint32_t i);
private:
std::vector<const uint16_t *> m_parents;
struct ConstructorInformation {
ns3::CallbackBase cb;
uint32_t nArguments;
};
struct IidInformation {
std::string name;
uint16_t parent;
std::vector<struct ConstructorInformation> constructors;
};
typedef std::vector<struct IidInformation>::const_iterator Iterator;
struct IidManager::IidInformation *LookupInformation (uint16_t uid) const;
std::vector<struct IidInformation> m_information;
};
void
IidTree::SetParent (uint16_t child, const uint16_t *parent)
uint16_t
IidManager::AllocateUid (std::string name)
{
m_parents.resize (child+1);
m_parents[child] = parent;
uint16_t j = 1;
for (Iterator i = m_information.begin (); i != m_information.end (); i++)
{
if (i->name == name)
{
NS_FATAL_ERROR ("Trying to allocate twice the same uid: " << name);
return 0;
}
j++;
}
struct IidInformation information;
information.name = name;
information.parent = 0;
m_information.push_back (information);
uint32_t uid = m_information.size ();
NS_ASSERT (uid <= 0xffff);
return uid;
}
struct IidManager::IidInformation *
IidManager::LookupInformation (uint16_t uid) const
{
NS_ASSERT (uid <= m_information.size ());
return const_cast<struct IidInformation *> (&m_information[uid-1]);
}
void
IidManager::SetParent (uint16_t uid, uint16_t parent)
{
NS_ASSERT (parent <= m_information.size ());
struct IidInformation *information = LookupInformation (uid);
information->parent = parent;
}
void
IidManager::AddConstructor (uint16_t uid, ns3::CallbackBase callback, uint32_t nArguments)
{
struct IidInformation *information = LookupInformation (uid);
struct ConstructorInformation constructor;
constructor.cb = callback;
constructor.nArguments = nArguments;
for (std::vector<struct ConstructorInformation>::const_iterator i = information->constructors.begin ();
i != information->constructors.end (); i++)
{
if (i->nArguments == nArguments)
{
NS_FATAL_ERROR ("registered two constructors on the same type with the same number of arguments.");
break;
}
}
information->constructors.push_back (constructor);
}
uint16_t
IidManager::GetUid (std::string name) const
{
uint32_t j = 1;
for (Iterator i = m_information.begin (); i != m_information.end (); i++)
{
if (i->name == name)
{
NS_ASSERT (j <= 0xffff);
return j;
}
j++;
}
return 0;
}
std::string
IidManager::GetName (uint16_t uid) const
{
struct IidInformation *information = LookupInformation (uid);
return information->name;
}
uint16_t
IidTree::LookupParent (uint16_t child)
IidManager::GetParent (uint16_t uid) const
{
NS_ASSERT (child < m_parents.size ());
return *(m_parents[child]);
struct IidInformation *information = LookupInformation (uid);
return information->parent;
}
ns3::CallbackBase
IidManager::GetConstructor (uint16_t uid, uint32_t nArguments)
{
struct IidInformation *information = LookupInformation (uid);
for (std::vector<struct ConstructorInformation>::const_iterator i = information->constructors.begin ();
i != information->constructors.end (); i++)
{
if (i->nArguments == nArguments)
{
return i->cb;
}
}
NS_FATAL_ERROR ("Requested constructor with "<<nArguments<<" arguments not found");
return ns3::CallbackBase ();
}
bool
IidManager::HasConstructor (uint16_t uid)
{
struct IidInformation *information = LookupInformation (uid);
return !information->constructors.empty ();
}
uint32_t
IidManager::GetRegisteredN (void)
{
return m_information.size ();
}
uint16_t
IidManager::GetRegistered (uint32_t i)
{
return i + 1;
}
} // anonymous namespace
/*********************************************************************
* The TypeId TraceResolver
*********************************************************************/
namespace ns3 {
class InterfaceIdTraceResolver : public TraceResolver
class TypeIdTraceResolver : public TraceResolver
{
public:
InterfaceIdTraceResolver (Ptr<const Object> aggregate);
TypeIdTraceResolver (Ptr<const Object> aggregate);
virtual void Connect (std::string path, CallbackBase const &cb, const TraceContext &context);
virtual void Disconnect (std::string path, CallbackBase const &cb);
virtual void CollectSources (std::string path, const TraceContext &context,
@@ -74,11 +202,11 @@ private:
Ptr<const Object> m_aggregate;
};
InterfaceIdTraceResolver::InterfaceIdTraceResolver (Ptr<const Object> aggregate)
TypeIdTraceResolver::TypeIdTraceResolver (Ptr<const Object> aggregate)
: m_aggregate (aggregate)
{}
Ptr<const Object>
InterfaceIdTraceResolver::ParseForInterface (std::string path)
TypeIdTraceResolver::ParseForInterface (std::string path)
{
std::string element = GetElement (path);
std::string::size_type dollar_pos = element.find ("$");
@@ -87,12 +215,12 @@ InterfaceIdTraceResolver::ParseForInterface (std::string path)
return 0;
}
std::string interfaceName = element.substr (1, std::string::npos);
InterfaceId interfaceId = InterfaceId::LookupByName (interfaceName);
Ptr<Object> interface = m_aggregate->QueryInterface<Object> (interfaceId);
TypeId interfaceId = TypeId::LookupByName (interfaceName);
Ptr<Object> interface = m_aggregate->GetObject<Object> (interfaceId);
return interface;
}
void
InterfaceIdTraceResolver::Connect (std::string path, CallbackBase const &cb, const TraceContext &context)
void
TypeIdTraceResolver::Connect (std::string path, CallbackBase const &cb, const TraceContext &context)
{
Ptr<const Object> interface = ParseForInterface (path);
if (interface != 0)
@@ -101,7 +229,7 @@ InterfaceIdTraceResolver::Connect (std::string path, CallbackBase const &cb, con
}
}
void
InterfaceIdTraceResolver::Disconnect (std::string path, CallbackBase const &cb)
TypeIdTraceResolver::Disconnect (std::string path, CallbackBase const &cb)
{
Ptr<const Object> interface = ParseForInterface (path);
if (interface != 0)
@@ -110,77 +238,136 @@ InterfaceIdTraceResolver::Disconnect (std::string path, CallbackBase const &cb)
}
}
void
InterfaceIdTraceResolver::CollectSources (std::string path, const TraceContext &context,
TypeIdTraceResolver::CollectSources (std::string path, const TraceContext &context,
SourceCollection *collection)
{
m_aggregate->DoCollectSources (path, context, collection);
}
void
InterfaceIdTraceResolver::TraceAll (std::ostream &os, const TraceContext &context)
TypeIdTraceResolver::TraceAll (std::ostream &os, const TraceContext &context)
{
m_aggregate->DoTraceAll (os, context);
}
/*********************************************************************
* The TypeId class
*********************************************************************/
InterfaceId::InterfaceId (uint16_t iid)
: m_iid (iid)
{}
InterfaceId::~InterfaceId ()
{}
InterfaceId
InterfaceId::LookupByName (std::string name)
TypeId::TypeId (std::string name)
{
uint32_t uid = Singleton<IidManager>::Get ()->LookupByName (name);
NS_ASSERT (uid != 0 && uid <= 0xffff);
return InterfaceId (uid);
uint16_t uid = Singleton<IidManager>::Get ()->AllocateUid (name);
NS_ASSERT (uid != 0);
m_tid = uid;
}
InterfaceId
InterfaceId::LookupParent (InterfaceId iid)
TypeId::TypeId (uint16_t tid)
: m_tid (tid)
{}
TypeId::~TypeId ()
{}
TypeId
TypeId::LookupByName (std::string name)
{
return Singleton<IidTree>::Get ()->LookupParent (iid.m_iid);
uint16_t uid = Singleton<IidManager>::Get ()->GetUid (name);
NS_ASSERT (uid != 0);
return TypeId (uid);
}
uint32_t
TypeId::GetRegisteredN (void)
{
return Singleton<IidManager>::Get ()->GetRegisteredN ();
}
TypeId
TypeId::GetRegistered (uint32_t i)
{
return TypeId (Singleton<IidManager>::Get ()->GetRegistered (i));
}
TypeId
TypeId::SetParent (TypeId tid)
{
Singleton<IidManager>::Get ()->SetParent (m_tid, tid.m_tid);
return *this;
}
TypeId
TypeId::GetParent (void) const
{
uint16_t parent = Singleton<IidManager>::Get ()->GetParent (m_tid);
return TypeId (parent);
}
std::string
InterfaceId::GetName (void) const
TypeId::GetName (void) const
{
std::string name = Singleton<IidManager>::Get ()->LookupByUid (m_iid);
std::string name = Singleton<IidManager>::Get ()->GetName (m_tid);
return name;
}
bool operator == (const InterfaceId &a, const InterfaceId &b)
bool
TypeId::HasConstructor (void) const
{
return a.m_iid == b.m_iid;
bool hasConstructor = Singleton<IidManager>::Get ()->HasConstructor (m_tid);
return hasConstructor;
}
bool operator != (const InterfaceId &a, const InterfaceId &b)
void
TypeId::DoAddConstructor (CallbackBase cb, uint32_t nArguments)
{
return a.m_iid != b.m_iid;
Singleton<IidManager>::Get ()->AddConstructor (m_tid, cb, nArguments);
}
InterfaceId
MakeInterfaceId (std::string name, const InterfaceId &parent)
CallbackBase
TypeId::LookupConstructor (uint32_t nArguments)
{
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;
CallbackBase constructor = Singleton<IidManager>::Get ()->GetConstructor (m_tid, nArguments);
return constructor;
}
InterfaceId
MakeObjectInterfaceId (void)
Ptr<Object>
TypeId::CreateObject (void)
{
InterfaceId iid = Singleton<IidManager>::Get ()->Allocate ("Object");
Singleton<IidTree>::Get ()->SetParent (iid.m_iid, &iid.m_iid);
return iid;
CallbackBase cb = LookupConstructor (0);
Callback<Ptr<Object> > realCb;
realCb.Assign (cb);
Ptr<Object> object = realCb ();
return object;
}
bool operator == (TypeId a, TypeId b)
{
return a.m_tid == b.m_tid;
}
const InterfaceId Object::iid = MakeObjectInterfaceId ();
bool operator != (TypeId a, TypeId b)
{
return a.m_tid != b.m_tid;
}
/*********************************************************************
* The Object implementation
*********************************************************************/
NS_OBJECT_ENSURE_REGISTERED (Object);
static TypeId
GetObjectIid (void)
{
TypeId tid = TypeId ("Object");
tid.SetParent (tid);
return tid;
}
TypeId
Object::GetTypeId (void)
{
static TypeId tid = GetObjectIid ();
return tid;
}
Object::Object ()
: m_count (1),
m_iid (Object::iid),
m_tid (Object::GetTypeId ()),
m_disposed (false),
m_collecting (false),
m_next (this)
@@ -190,18 +377,18 @@ Object::~Object ()
m_next = 0;
}
Ptr<Object>
Object::DoQueryInterface (InterfaceId iid) const
Object::DoGetObject (TypeId tid) const
{
NS_ASSERT (CheckLoose ());
const Object *currentObject = this;
do {
NS_ASSERT (currentObject != 0);
InterfaceId cur = currentObject->m_iid;
while (cur != iid && cur != Object::iid)
TypeId cur = currentObject->m_tid;
while (cur != tid && cur != Object::GetTypeId ())
{
cur = InterfaceId::LookupParent (cur);
cur = cur.GetParent ();
}
if (cur == iid)
if (cur == tid)
{
return const_cast<Object *> (currentObject);
}
@@ -223,7 +410,7 @@ Object::Dispose (void)
}
void
Object::AddInterface (Ptr<Object> o)
Object::AggregateObject (Ptr<Object> o)
{
NS_ASSERT (!m_disposed);
NS_ASSERT (!o->m_disposed);
@@ -251,10 +438,10 @@ Object::TraceDisconnect (std::string path, const CallbackBase &cb) const
}
void
Object::SetInterfaceId (InterfaceId iid)
Object::SetTypeId (TypeId tid)
{
NS_ASSERT (Check ());
m_iid = iid;
m_tid = tid;
}
void
@@ -267,8 +454,8 @@ Ptr<TraceResolver>
Object::GetTraceResolver (void) const
{
NS_ASSERT (CheckLoose ());
Ptr<InterfaceIdTraceResolver> resolver =
Create<InterfaceIdTraceResolver> (this);
Ptr<TypeIdTraceResolver> resolver =
Create<TypeIdTraceResolver> (this);
return resolver;
}
@@ -348,8 +535,8 @@ Object::DoCollectSources (std::string path, const TraceContext &context,
{
NS_ASSERT (current != 0);
NS_LOG_LOGIC ("collect current=" << current);
InterfaceId cur = current->m_iid;
while (cur != Object::iid)
TypeId cur = current->m_tid;
while (cur != Object::GetTypeId ())
{
std::string name = cur.GetName ();
std::string fullpath = path;
@@ -357,7 +544,7 @@ Object::DoCollectSources (std::string path, const TraceContext &context,
fullpath.append (name);
NS_LOG_LOGIC("collect: " << fullpath);
current->GetTraceResolver ()->CollectSources (fullpath, context, collection);
cur = InterfaceId::LookupParent (cur);
cur = cur.GetParent ();
}
current = current->m_next;
}
@@ -404,11 +591,14 @@ namespace {
class BaseA : public ns3::Object
{
public:
static const ns3::InterfaceId iid;
BaseA ()
{
SetInterfaceId (BaseA::iid);
static ns3::TypeId GetTypeId (void) {
static ns3::TypeId tid = ns3::TypeId ("BaseA")
.SetParent (Object::GetTypeId ())
.AddConstructor<BaseA> ();
return tid;
}
BaseA ()
{}
void BaseGenerateTrace (int16_t v)
{ m_source = v; }
virtual void Dispose (void) {}
@@ -426,11 +616,14 @@ public:
class DerivedA : public BaseA
{
public:
static const ns3::InterfaceId iid;
DerivedA (int v)
{
SetInterfaceId (DerivedA::iid);
static ns3::TypeId GetTypeId (void) {
static ns3::TypeId tid = ns3::TypeId ("DerivedA")
.SetParent (BaseA::GetTypeId ())
.AddConstructor<DerivedA,int> ();
return tid;
}
DerivedA (int v)
{}
void DerivedGenerateTrace (int16_t v)
{ m_sourceDerived = v; }
virtual void Dispose (void) {
@@ -447,19 +640,17 @@ public:
ns3::SVTraceSource<int16_t> m_sourceDerived;
};
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);
static ns3::TypeId GetTypeId (void) {
static ns3::TypeId tid = ns3::TypeId ("BaseB")
.SetParent (Object::GetTypeId ())
.AddConstructor<BaseB> ();
return tid;
}
BaseB ()
{}
void BaseGenerateTrace (int16_t v)
{ m_source = v; }
virtual void Dispose (void) {}
@@ -477,11 +668,17 @@ public:
class DerivedB : public BaseB
{
public:
static const ns3::InterfaceId iid;
DerivedB (int v)
{
SetInterfaceId (DerivedB::iid);
static ns3::TypeId GetTypeId (void) {
static ns3::TypeId tid = ns3::TypeId ("DerivedB")
.SetParent (BaseB::GetTypeId ())
.AddConstructor<DerivedB,int> ()
.AddConstructor<DerivedB,int,int &> ();
return tid;
}
DerivedB (int v)
{}
DerivedB (int v1, int &v2)
{}
void DerivedGenerateTrace (int16_t v)
{ m_sourceDerived = v; }
virtual void Dispose (void) {
@@ -498,10 +695,10 @@ public:
ns3::SVTraceSource<int16_t> m_sourceDerived;
};
const ns3::InterfaceId BaseB::iid =
ns3::MakeInterfaceId ("BaseB", Object::iid);
const ns3::InterfaceId DerivedB::iid =
ns3::MakeInterfaceId ("DerivedB", BaseB::iid);;
NS_OBJECT_ENSURE_REGISTERED (BaseA);
NS_OBJECT_ENSURE_REGISTERED (DerivedA);
NS_OBJECT_ENSURE_REGISTERED (BaseB);
NS_OBJECT_ENSURE_REGISTERED (DerivedB);
} // namespace anonymous
@@ -553,63 +750,63 @@ ObjectTest::RunTests (void)
{
bool result = true;
Ptr<BaseA> baseA = Create<BaseA> ();
NS_TEST_ASSERT_EQUAL (baseA->QueryInterface<BaseA> (BaseA::iid), baseA);
NS_TEST_ASSERT_EQUAL (baseA->QueryInterface<BaseA> (DerivedA::iid), 0);
NS_TEST_ASSERT_EQUAL (baseA->QueryInterface<DerivedA> (DerivedA::iid), 0);
baseA = Create<DerivedA> (10);
NS_TEST_ASSERT_EQUAL (baseA->QueryInterface<BaseA> (BaseA::iid), baseA);
NS_TEST_ASSERT_EQUAL (baseA->QueryInterface<BaseA> (DerivedA::iid), baseA);
NS_TEST_ASSERT_UNEQUAL (baseA->QueryInterface<DerivedA> (DerivedA::iid), 0);
Ptr<BaseA> baseA = CreateObject<BaseA> ();
NS_TEST_ASSERT_EQUAL (baseA->GetObject<BaseA> (), baseA);
NS_TEST_ASSERT_EQUAL (baseA->GetObject<BaseA> (DerivedA::GetTypeId ()), 0);
NS_TEST_ASSERT_EQUAL (baseA->GetObject<DerivedA> (), 0);
baseA = CreateObject<DerivedA> (10);
NS_TEST_ASSERT_EQUAL (baseA->GetObject<BaseA> (), baseA);
NS_TEST_ASSERT_EQUAL (baseA->GetObject<BaseA> (DerivedA::GetTypeId ()), baseA);
NS_TEST_ASSERT_UNEQUAL (baseA->GetObject<DerivedA> (), 0);
baseA = Create<BaseA> ();
Ptr<BaseB> baseB = Create<BaseB> ();
baseA = CreateObject<BaseA> ();
Ptr<BaseB> baseB = CreateObject<BaseB> ();
Ptr<BaseB> baseBCopy = baseB;
baseA->AddInterface (baseB);
NS_TEST_ASSERT_UNEQUAL (baseA->QueryInterface<BaseA> (BaseA::iid), 0);
NS_TEST_ASSERT_EQUAL (baseA->QueryInterface<DerivedA> (DerivedA::iid), 0);
NS_TEST_ASSERT_UNEQUAL (baseA->QueryInterface<BaseB> (BaseB::iid), 0);
NS_TEST_ASSERT_EQUAL (baseA->QueryInterface<DerivedB> (DerivedB::iid), 0);
NS_TEST_ASSERT_UNEQUAL (baseB->QueryInterface<BaseB> (BaseB::iid), 0);
NS_TEST_ASSERT_EQUAL (baseB->QueryInterface<DerivedB> (DerivedB::iid), 0);
NS_TEST_ASSERT_UNEQUAL (baseB->QueryInterface<BaseA> (BaseA::iid), 0);
NS_TEST_ASSERT_EQUAL (baseB->QueryInterface<DerivedA> (DerivedA::iid), 0);
NS_TEST_ASSERT_UNEQUAL (baseBCopy->QueryInterface<BaseA> (BaseA::iid), 0);
baseA->AggregateObject (baseB);
NS_TEST_ASSERT_UNEQUAL (baseA->GetObject<BaseA> (), 0);
NS_TEST_ASSERT_EQUAL (baseA->GetObject<DerivedA> (), 0);
NS_TEST_ASSERT_UNEQUAL (baseA->GetObject<BaseB> (), 0);
NS_TEST_ASSERT_EQUAL (baseA->GetObject<DerivedB> (), 0);
NS_TEST_ASSERT_UNEQUAL (baseB->GetObject<BaseB> (), 0);
NS_TEST_ASSERT_EQUAL (baseB->GetObject<DerivedB> (), 0);
NS_TEST_ASSERT_UNEQUAL (baseB->GetObject<BaseA> (), 0);
NS_TEST_ASSERT_EQUAL (baseB->GetObject<DerivedA> (), 0);
NS_TEST_ASSERT_UNEQUAL (baseBCopy->GetObject<BaseA> (), 0);
baseA = Create<DerivedA> (1);
baseB = Create<DerivedB> (1);
baseA = CreateObject<DerivedA> (1);
baseB = CreateObject<DerivedB> (1);
baseBCopy = baseB;
baseA->AddInterface (baseB);
NS_TEST_ASSERT_UNEQUAL (baseA->QueryInterface<DerivedB> (DerivedB::iid), 0);
NS_TEST_ASSERT_UNEQUAL (baseA->QueryInterface<BaseB> (BaseB::iid), 0);
NS_TEST_ASSERT_UNEQUAL (baseB->QueryInterface<DerivedA> (DerivedA::iid), 0);
NS_TEST_ASSERT_UNEQUAL (baseB->QueryInterface<BaseA> (BaseA::iid), 0);
NS_TEST_ASSERT_UNEQUAL (baseBCopy->QueryInterface<DerivedA> (DerivedA::iid), 0);
NS_TEST_ASSERT_UNEQUAL (baseBCopy->QueryInterface<BaseA> (BaseA::iid), 0);
NS_TEST_ASSERT_UNEQUAL (baseB->QueryInterface<DerivedB> (DerivedB::iid), 0);
NS_TEST_ASSERT_UNEQUAL (baseB->QueryInterface<BaseB> (BaseB::iid), 0)
baseA->AggregateObject (baseB);
NS_TEST_ASSERT_UNEQUAL (baseA->GetObject<DerivedB> (), 0);
NS_TEST_ASSERT_UNEQUAL (baseA->GetObject<BaseB> (), 0);
NS_TEST_ASSERT_UNEQUAL (baseB->GetObject<DerivedA> (), 0);
NS_TEST_ASSERT_UNEQUAL (baseB->GetObject<BaseA> (), 0);
NS_TEST_ASSERT_UNEQUAL (baseBCopy->GetObject<DerivedA> (), 0);
NS_TEST_ASSERT_UNEQUAL (baseBCopy->GetObject<BaseA> (), 0);
NS_TEST_ASSERT_UNEQUAL (baseB->GetObject<DerivedB> (), 0);
NS_TEST_ASSERT_UNEQUAL (baseB->GetObject<BaseB> (), 0)
baseA = Create<BaseA> ();
baseB = Create<BaseB> ();
baseA->AddInterface (baseB);
baseA = CreateObject<BaseA> ();
baseB = CreateObject<BaseB> ();
baseA->AggregateObject (baseB);
baseA = 0;
baseA = baseB->QueryInterface<BaseA> (BaseA::iid);
baseA = baseB->GetObject<BaseA> ();
baseA = Create<BaseA> ();
baseA = CreateObject<BaseA> ();
baseA->TraceConnect ("/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
m_baseATrace = false;
baseA->BaseGenerateTrace (1);
NS_TEST_ASSERT (m_baseATrace);
baseA->TraceDisconnect ("/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
baseB = Create<BaseB> ();
baseB = CreateObject<BaseB> ();
baseB->TraceConnect ("/baseb-x", MakeCallback (&ObjectTest::BaseBTrace, this));
m_baseBTrace = false;
baseB->BaseGenerateTrace (2);
NS_TEST_ASSERT (m_baseBTrace);
baseB->TraceDisconnect ("/baseb-x", MakeCallback (&ObjectTest::BaseBTrace, this));
baseA->AddInterface (baseB);
baseA->AggregateObject (baseB);
baseA->TraceConnect ("/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
m_baseATrace = false;
@@ -639,9 +836,9 @@ ObjectTest::RunTests (void)
baseA->TraceDisconnect ("/$BaseA/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
Ptr<DerivedA> derivedA;
derivedA = Create<DerivedA> (1);
baseB = Create<BaseB> ();
derivedA->AddInterface (baseB);
derivedA = CreateObject<DerivedA> (1);
baseB = CreateObject<BaseB> ();
derivedA->AggregateObject (baseB);
baseB->TraceConnect ("/$DerivedA/deriveda-x", MakeCallback (&ObjectTest::DerivedATrace, this));
baseB->TraceConnect ("/$DerivedA/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
m_derivedATrace = false;
@@ -664,6 +861,17 @@ ObjectTest::RunTests (void)
NS_TEST_ASSERT (m_derivedATrace);
baseB->TraceDisconnect ("/$DerivedA/*", MakeCallback (&ObjectTest::BaseATrace, this));
// Test the object creation code of TypeId
Ptr<Object> a = BaseA::GetTypeId ().CreateObject ();
NS_TEST_ASSERT_EQUAL (a->GetObject<BaseA> (), a);
NS_TEST_ASSERT_EQUAL (a->GetObject<BaseA> (DerivedA::GetTypeId ()), 0);
NS_TEST_ASSERT_EQUAL (a->GetObject<DerivedA> (), 0);
a = DerivedA::GetTypeId ().CreateObject (10);
NS_TEST_ASSERT_EQUAL (a->GetObject<BaseA> (), a);
NS_TEST_ASSERT_EQUAL (a->GetObject<BaseA> (DerivedA::GetTypeId ()), a);
NS_TEST_ASSERT_UNEQUAL (a->GetObject<DerivedA> (), 0);
return result;
}
+354 -53
View File
@@ -25,21 +25,30 @@
#include <string>
#include "ptr.h"
#include "trace-resolver.h"
#include "callback.h"
#include "empty.h"
#define NS_OBJECT_ENSURE_REGISTERED(type) \
static struct X##type##RegistrationClass \
{ \
X##type##RegistrationClass () { \
ns3::TypeId tid = type::GetTypeId (); \
tid.GetParent (); \
} \
} x_##type##RegistrationVariable
namespace ns3 {
class TraceContext;
class CallbackBase;
class Object;
/**
* \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
class TypeId
{
public:
/**
@@ -50,55 +59,85 @@ public:
* This method cannot fail: it will crash if the input
* name is not a valid interface name.
*/
static InterfaceId LookupByName (std::string name);
static TypeId LookupByName (std::string name);
static uint32_t GetRegisteredN (void);
static TypeId GetRegistered (uint32_t i);
/**
* \param iid a unique id
* \returns the parent of the requested id, as registered
* by ns3::MakeInterfaceId.
* \returns the parent of this TypeId
*
* This method cannot fail: it will crash if the input
* id is not a valid interface id.
* This method cannot fail. It will return itself
* if this TypeId has no parent. i.e., it is at the top
* of the TypeId hierarchy. Currently, this is the
* case for the TypeId associated to the Object class
* only.
*/
static InterfaceId LookupParent (InterfaceId iid);
TypeId GetParent (void) const;
/**
* \returns the name of this interface.
*/
std::string GetName (void) const;
~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);
/**
* \returns true if this TypeId has a constructor
*/
bool HasConstructor (void) const;
TypeId (std::string);
TypeId SetParent (TypeId tid);
template <typename T>
TypeId SetParent (void);
template <typename T>
TypeId AddConstructor (void);
template <typename T, typename T1>
TypeId AddConstructor (void);
template <typename T, typename T1, typename T2>
TypeId AddConstructor (void);
template <typename T, typename T1, typename T2, typename T3>
TypeId AddConstructor (void);
template <typename T, typename T1, typename T2, typename T3, typename T4>
TypeId AddConstructor (void);
template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
TypeId AddConstructor (void);
Ptr<Object> CreateObject (void);
template <typename T1>
Ptr<Object> CreateObject (T1 a1);
template <typename T1, typename T2>
Ptr<Object> CreateObject (T1 a1, T2 a2);
template <typename T1, typename T2, typename T3>
Ptr<Object> CreateObject (T1 a1, T2 a2, T3 a3);
template <typename T1, typename T2, typename T3, typename T4>
Ptr<Object> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4);
template <typename T1, typename T2, typename T3, typename T4, typename T5>
Ptr<Object> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
~TypeId ();
private:
friend bool operator == (TypeId a, TypeId b);
friend bool operator != (TypeId a, TypeId b);
explicit TypeId (uint16_t tid);
void DoAddConstructor (CallbackBase callback, uint32_t nArguments);
CallbackBase LookupConstructor (uint32_t nArguments);
uint16_t m_tid;
};
/**
* \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.
* GetObject.
*/
class Object
{
public:
static const InterfaceId iid;
static TypeId GetTypeId (void);
Object ();
virtual ~Object ();
@@ -117,12 +156,16 @@ public:
*/
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;
Ptr<T> GetObject (void) const;
/**
* \param tid the interface id of the requested interface
* \returns a pointer to the requested interface or zero if it could not be found.
*/
template <typename T>
Ptr<T> GetObject (TypeId tid) const;
/**
* Run the DoDispose methods of this object and all the
* objects aggregated to it.
@@ -136,10 +179,10 @@ public:
* \param other another object pointer
*
* This method aggregates the two objects together: after this
* method returns, it becomes possible to call QueryInterface
* method returns, it becomes possible to call GetObject
* on one to get the other, and vice-versa.
*/
void AddInterface (Ptr<Object> other);
void AggregateObject (Ptr<Object> other);
/**
* \param path the path to match for the callback
@@ -165,14 +208,6 @@ public:
*/
virtual Ptr<TraceResolver> GetTraceResolver (void) const;
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
@@ -180,25 +215,214 @@ protected:
*/
virtual void DoDispose (void);
private:
friend class InterfaceIdTraceResolver;
Ptr<Object> DoQueryInterface (InterfaceId iid) const;
friend class TypeIdTraceResolver;
template <typename T>
friend Ptr<T> CreateObject (void);
template <typename T, typename T1>
friend Ptr<T> CreateObject (T1 a1);
template <typename T, typename T1, typename T2>
friend Ptr<T> CreateObject (T1 a1, T2 a2);
template <typename T, typename T1, typename T2, typename T3>
friend Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3);
template <typename T, typename T1, typename T2, typename T3, typename T4>
friend Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4);
template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
friend Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
friend Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6);
template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
friend Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7);
Ptr<Object> DoGetObject (TypeId tid) const;
void DoCollectSources (std::string path, const TraceContext &context,
TraceResolver::SourceCollection *collection) const;
void DoTraceAll (std::ostream &os, const TraceContext &context) const;
bool Check (void) const;
bool CheckLoose (void) const;
void MaybeDelete (void) const;
/**
* \param tid an TypeId
*
* Every subclass which defines a new TypeId for itself
* should register this TypeId by calling this method
* from its constructor.
*/
void SetTypeId (TypeId tid);
mutable uint32_t m_count;
InterfaceId m_iid;
TypeId m_tid;
bool m_disposed;
mutable bool m_collecting;
Object *m_next;
};
template <typename T>
Ptr<T> CreateObject (void);
template <typename T, typename T1>
Ptr<T> CreateObject (T1 a1);
template <typename T, typename T1, typename T2>
Ptr<T> CreateObject (T1 a1, T2 a2);
template <typename T, typename T1, typename T2, typename T3>
Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3);
template <typename T, typename T1, typename T2, typename T3, typename T4>
Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4);
template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6);
template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7);
} // namespace ns3
namespace ns3 {
template <typename T>
TypeId
TypeId::SetParent (void)
{
return SetParent (T::GetTypeId ());
}
template <typename T>
TypeId
TypeId::AddConstructor (void)
{
struct Maker {
static Ptr<Object> Create (void) {
return ns3::CreateObject<T> ();
}
};
CallbackBase cb = MakeCallback (&Maker::Create);
DoAddConstructor (cb, 0);
return *this;
}
template <typename T, typename T1>
TypeId
TypeId::AddConstructor (void)
{
struct Maker {
static Ptr<Object> Create (T1 a1) {
return ns3::CreateObject<T,T1> (a1);
}
};
CallbackBase cb = MakeCallback (&Maker::Create);
DoAddConstructor (cb, 1);
return *this;
}
template <typename T, typename T1, typename T2>
TypeId
TypeId::AddConstructor (void)
{
struct Maker {
static Ptr<Object> Create (T1 a1, T2 a2) {
return ns3::CreateObject<T,T1,T2> (a1, a2);
}
};
CallbackBase cb = MakeCallback (&Maker::Create);
DoAddConstructor (cb, 2);
return *this;
}
template <typename T, typename T1, typename T2, typename T3>
TypeId
TypeId::AddConstructor (void)
{
struct Maker {
static Ptr<Object> Create (T1 a1, T2 a2, T3 a3) {
return ns3::CreateObject<T,T1,T2,T3> (a1, a2, a3);
}
};
CallbackBase cb = MakeCallback (&Maker::Create);
DoAddConstructor (cb, 3);
return *this;
}
template <typename T, typename T1, typename T2, typename T3, typename T4>
TypeId
TypeId::AddConstructor (void)
{
struct Maker {
static Ptr<Object> Create (T1 a1, T2 a2, T3 a3, T4 a4) {
return ns3::CreateObject<T,T1,T2,T3,T4> (a1, a2, a3, a4);
}
};
CallbackBase cb = MakeCallback (&Maker::Create);
DoAddConstructor (cb, 4);
return *this;
}
template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
TypeId
TypeId::AddConstructor (void)
{
struct Maker {
static Ptr<Object> Create (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) {
return ns3::CreateObject<T,T1,T2,T3,T4,T5> (a1, a2, a3, a4, a5);
}
};
CallbackBase cb = MakeCallback (&Maker::Create);
DoAddConstructor (cb, 5);
return *this;
}
template <typename T1>
Ptr<Object>
TypeId::CreateObject (T1 a1)
{
CallbackBase cb = LookupConstructor (1);
Callback<Ptr<Object>,T1> realCb;
realCb.Assign (cb);
Ptr<Object> object = realCb (a1);
return object;
}
template <typename T1, typename T2>
Ptr<Object>
TypeId::CreateObject (T1 a1, T2 a2)
{
CallbackBase cb = LookupConstructor (2);
Callback<Ptr<Object>,T1,T2> realCb;
realCb.Assign (cb);
Ptr<Object> object = realCb (a1,a2);
return object;
}
template <typename T1, typename T2, typename T3>
Ptr<Object>
TypeId::CreateObject (T1 a1, T2 a2, T3 a3)
{
CallbackBase cb = LookupConstructor (3);
Callback<Ptr<Object>,T1,T2,T3> realCb;
realCb.Assign (cb);
Ptr<Object> object = realCb (a1,a2,a3);
return object;
}
template <typename T1, typename T2, typename T3, typename T4>
Ptr<Object>
TypeId::CreateObject (T1 a1, T2 a2, T3 a3, T4 a4)
{
CallbackBase cb = LookupConstructor (4);
Callback<Ptr<Object>,T1,T2,T3,T4> realCb;
realCb.Assign (cb);
Ptr<Object> object = realCb (a1,a2,a3,a4);
return object;
}
template <typename T1, typename T2, typename T3, typename T4, typename T5>
Ptr<Object>
TypeId::CreateObject (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
{
CallbackBase cb = LookupConstructor (5);
Callback<Ptr<Object>,T1,T2,T3,T4,T5> realCb;
realCb.Assign (cb);
Ptr<Object> object = realCb (a1,a2,a3,a4,a5);
return object;
}
void
Object::Ref (void) const
{
@@ -217,9 +441,9 @@ Object::Unref (void) const
template <typename T>
Ptr<T>
Object::QueryInterface (InterfaceId iid) const
Object::GetObject () const
{
Ptr<Object> found = DoQueryInterface (iid);
Ptr<Object> found = DoGetObject (T::GetTypeId ());
if (found != 0)
{
return Ptr<T> (dynamic_cast<T *> (PeekPointer (found)));
@@ -227,6 +451,83 @@ Object::QueryInterface (InterfaceId iid) const
return 0;
}
template <typename T>
Ptr<T>
Object::GetObject (TypeId tid) const
{
Ptr<Object> found = DoGetObject (tid);
if (found != 0)
{
return Ptr<T> (dynamic_cast<T *> (PeekPointer (found)));
}
return 0;
}
template <typename T>
Ptr<T> CreateObject (void)
{
Ptr<T> p = Ptr<T> (new T (), false);
p->SetTypeId (T::GetTypeId ());
return p;
}
template <typename T, typename T1>
Ptr<T> CreateObject (T1 a1)
{
Ptr<T> p = Ptr<T> (new T (a1), false);
p->SetTypeId (T::GetTypeId ());
return p;
}
template <typename T, typename T1, typename T2>
Ptr<T> CreateObject (T1 a1, T2 a2)
{
Ptr<T> p = Ptr<T> (new T (a1, a2), false);
p->SetTypeId (T::GetTypeId ());
return p;
}
template <typename T, typename T1, typename T2, typename T3>
Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3)
{
Ptr<T> p = Ptr<T> (new T (a1, a2, a3), false);
p->SetTypeId (T::GetTypeId ());
return p;
}
template <typename T, typename T1, typename T2, typename T3, typename T4>
Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4)
{
Ptr<T> p = Ptr<T> (new T (a1, a2, a3, a4), false);
p->SetTypeId (T::GetTypeId ());
return p;
}
template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
{
Ptr<T> p = Ptr<T> (new T (a1, a2, a3, a4, a5), false);
p->SetTypeId (T::GetTypeId ());
return p;
}
template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6)
{
Ptr<T> p = Ptr<T> (new T (a1, a2, a3, a4, a5, a6), false);
p->SetTypeId (T::GetTypeId ());
return p;
}
template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7)
{
Ptr<T> p = Ptr<T> (new T (a1, a2, a3, a4, a5, a6, a7), false);
p->SetTypeId (T::GetTypeId ());
return p;
}
} // namespace ns3
#endif /* OBJECT_H */

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