From 886ebc725b55b976f2b40c185dec80d2d561685f Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Fri, 13 Nov 2009 09:37:52 -0800 Subject: [PATCH] HOWTOs are now on the wiki --- doc/howtos/howtos-application.h | 203 ------------------------------ doc/howtos/howtos-callbacks.h | 38 ------ doc/howtos/howtos-net-device.h | 162 ------------------------ doc/howtos/howtos-packet-header.h | 119 ------------------ doc/howtos/howtos.h | 20 --- doc/main.h | 6 +- 6 files changed, 3 insertions(+), 545 deletions(-) delete mode 100644 doc/howtos/howtos-application.h delete mode 100644 doc/howtos/howtos-callbacks.h delete mode 100644 doc/howtos/howtos-net-device.h delete mode 100644 doc/howtos/howtos-packet-header.h delete mode 100644 doc/howtos/howtos.h diff --git a/doc/howtos/howtos-application.h b/doc/howtos/howtos-application.h deleted file mode 100644 index 33ba848c3..000000000 --- a/doc/howtos/howtos-application.h +++ /dev/null @@ -1,203 +0,0 @@ -/*! - \page application How to create a traffic generator ? - \anchor howtos-application - - Question: How do I create a new traffic generator ? - - Answer: It is possible to instanciate \ref ns3::Packet "Packet" - objects, schedule events, and call functions from any piece of code - in ns-3 so, technically, there is no single answer to the question of - how we can write a new traffic generator. However, the - \ref ns3::Socket "Socket" API was really designed to be the single - point of entry for traffic generators or traffic analysers and the - \ref ns3::Application "Application" class was designed to hold - together any number of sockets. - - Implementing a new traffic generator thus boils down to: -- implementing a new subclass of the \ref ns3::Application "Application" - base class -- instanciate one or many sockets within that application -- start scheduling events when \ref ns3::Application::StartApplication "StartApplication" - is called -- stop scheduling events when \ref ns3::Application::StopApplication "StopApplication" - is called -- create packets and send them over one or many sockets in each event - -The following "random" generator generates packets separated by a random -delay and with a random size. - -\code -class RandomGenerator : public Application -{ -public: - RandomGenerator (); - void SetDelay (RandomVariable delay); - void SetSize (RandomVariable size); - void SetRemote (std::string socketType, - Address remote); -private: - virtual void StartApplication (void); - virtual void StopApplication (void); - void DoGenerate (void); - - RandomVariable m_delay; - RandomVariable m_size; - Ptr m_socket; -}; -\endcode - -The socket is created in the SetRemote method: -\code -void -RandomGenerator::SetRemote (std::string socketType, - Address remote) -{ - TypeId tid = TypeId::LookupByName (socketType); - m_socket = Socket::CreateSocket (GetNode (), tid); - m_socket->Bind (); - m_socket->ShutdownRecv (); - m_socket->Connect (remote); -} -\endcode -While the the crux of the logic is located in the DoGenerate method -which is called from within StartApplication: -\code -void -RandomGenerator::DoGenerate (void) -{ - m_next = Simulator::Schedule (Seconds (m_delay.GetValue ()), - &RandomGenerator::DoGenerate, this); - Ptr p = Create (m_size.GetIntValue ()); - m_socket->Send (p); -} -\endcode - -To make that application more integrated in ns-3, it needs an associated -helper class: -\code -class RandomAppHelper -{ -public: - RandomAppHelper (std::string protocol, Address remote); - void SetPacketSize (RandomVariable packetSize); - void SetDelay (RandomVariable delay); - ApplicationContainer Install (NodeContainer nodes); -private: - std::string m_protocol; - Address m_remote; - RandomVariable m_packetSize; - RandomVariable m_delay; -}; -\endcode - -which could be trivially implemented as: -\code -ApplicationContainer -RandomAppHelper::Install (NodeContainer nodes) -{ - ApplicationContainer applications; - for (NodeContainer::Iterator i = nodes.Begin (); i != nodes.End (); ++i) - { - Ptr app = CreateObject (); - app->SetSize (m_packetSize); - app->SetDelay (m_delay); - app->SetRemote (m_protocol, m_remote); - (*i)->AddApplication (app); - applications.Add (app); - } - return applications; -} -\endcode - -Despite being functional, this API is not very consistant with the style of -the other helper classes, all of which allow you to control the parameters -of the underlying class through attributes and not explicit setters. The -following API thus replaces the pair SetPacketSize/SetDelay with a single -method SetAttribute: -\code -class RandomAppHelper -{ -public: - RandomAppHelper (std::string protocol, Address remote); - void SetAttribute (std::string name, const AttributeValue &value); - ApplicationContainer Install (NodeContainer c); -private: - std::string m_protocol; - Address m_remote; - ObjectFactory m_factory; -}; -\endcode - -And which can be used as follows: -\code -RandomAppHelper app = RandomAppHelper ("ns3::TcpSocketFactory", - InetSocketAddress (Ipv4Address ("192.168.1.10"), 10)); -app.SetAttribute ("Delay", StringValue ("Constant:2.5")); -app.SetAttribute ("Size", StringValue ("Constant:2100")); -app.Install (nodes); -\endcode - -The implementation, in this case, is not necessarily longer but its -simplicity hides a lot of behind-the-scenes complexity: - -\code -void -RandomAppHelper::SetAttribute (std::string name, const AttributeValue &value) -{ - m_factory.Set (name, value); -} -ApplicationContainer -RandomAppHelper::Install (NodeContainer nodes) -{ - ApplicationContainer applications; - for (NodeContainer::Iterator i = nodes.Begin (); i != nodes.End (); ++i) - { - Ptr app = m_factory.Create (); - app->SetRemote (m_socketType, m_remote); - (*i)->AddApplication (app); - applications.Add (app); - } - return applications; -} -\endcode - -The key difference between this implementation and the previous one -is that this helper does not handle explicitely the attributes -delay and packet size. Instead, it stores them in an -\ref ns3::ObjectFactory "ObjectFactory" object. This, of course, -does not work magically, and requires extra support from the -underlying RandomGenerator class. Specifically, it requires -that the underlying RandomGenerator defines its attributes -in its \ref ns3::TypeId "TypeId" in a new public static method: - -\code -class RandomGenerator -{ -public: - static TypeId GetTypeId (void); -}; -\endcode - -The corresponding implementation is shown below: - -\code -TypeId -RandomGenerator::GetTypeId (void) -{ - static TypeId tid = TypeId ("RandomGenerator") - .SetParent () - .AddConstructor () - .AddAttribute ("Delay", "The delay between two packets (s)", - RandomVariableValue (ConstantVariable (1.0)), - MakeRandomVariableAccessor (&RandomGenerator::m_delay), - MakeRandomVariableChecker ()) - .AddAttribute ("PacketSize", "The size of each packet (bytes)", - RandomVariableValue (ConstantVariable (2000)), - MakeRandomVariableAccessor (&RandomGenerator::m_size), - MakeRandomVariableChecker ()) - ; - return tid; -} -\endcode - -*/ diff --git a/doc/howtos/howtos-callbacks.h b/doc/howtos/howtos-callbacks.h deleted file mode 100644 index c0a16654c..000000000 --- a/doc/howtos/howtos-callbacks.h +++ /dev/null @@ -1,38 +0,0 @@ -/*! -\page callbacks Using ns-3 callbacks -\anchor howtos-callbacks - -\section null_callbacks Null Callbacks - -Question: 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? - -Answer: Use the ns3::MakeNullCallback construct: -\code -template -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 > connectionSucceeded, - Callback > connectionFailed, - Callback > 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 > () ); -\endcode - -*/ diff --git a/doc/howtos/howtos-net-device.h b/doc/howtos/howtos-net-device.h deleted file mode 100644 index 00bb016e1..000000000 --- a/doc/howtos/howtos-net-device.h +++ /dev/null @@ -1,162 +0,0 @@ -/*! - \page net-device How to create a new OSI layer 1 + 2 implementation ? - \anchor howtos-net-device - - Question: How do I integrate a new OSI layer 1 + 2 implementation ? - - Answer: The OSI layers 1 and 2 are represented by the ns3::NetDevice - and ns3::Channel classes. To plug transparently in ns-3, a new layer 1+2 model - thus simply needs to provide two new subclasses of these two base classes. - - To make that subclassing process easy, two skeleton classes are provided in - the src/node directory: simple-net-device.h (ns3::SimpleNetDevice) and - simple-channel.h (ns3::SimpleChannel) implement a broadcast passthru medium - using 48bit MAC addresses without any kind of MAC access algorithm or PHY - layer modeling. - - The ns3::SimpleChannel class is really very simple: it provides - an implementation for the ns3::Channel::GetNDevices and ns3::Channel::GetDevice - methods defined in the Channel base class and, then defines the channel-specific - send and add methods: -- The Add method is used by SimpleNetDevice::SetChannel to register a new - SimpleNetDevice with its associated channel. -- The Send method is used by SimpleNetDevice::Send to send a packet over the - broadcast medium and ensure that it gets delivered to all associated devices - (except the sender). - -\code -class SimpleChannel : public Channel -{ -public: - static TypeId GetTypeId (void); - SimpleChannel (); - - void Send (Ptr p, uint16_t protocol, Mac48Address to, Mac48Address from, - Ptr sender); - - void Add (Ptr device); - - // inherited from ns3::Channel - virtual uint32_t GetNDevices (void) const; - virtual Ptr GetDevice (uint32_t i) const; - -private: - std::vector > m_devices; -}; -\endcode - -The SimpleNetDevice class is also trivial since it implements no special -MAC-layer processing: -\code -class SimpleNetDevice : public NetDevice -{ -public: - static TypeId GetTypeId (void); - SimpleNetDevice (); - - void Receive (Ptr packet, uint16_t protocol, Mac48Address to, Mac48Address from); - void SetChannel (Ptr channel); - void SetAddress (Mac48Address address); - - // inherited from NetDevice base class. - virtual void SetName(const std::string name); - ... -}; -\endcode - -The code below illustrates how the three model-specific methods defined above are -implemented: - -\code -void -SimpleNetDevice::Receive (Ptr packet, uint16_t protocol, - Mac48Address to, Mac48Address from) -{ - if (to == m_address || to == Mac48Address::GetBroadcast ()) - { - m_rxCallback (this, packet, protocol, from); - } -} -void -SimpleNetDevice::SetChannel (Ptr channel) -{ - m_channel = channel; - m_channel->Add (this); -} -void -SimpleNetDevice::SetAddress (Mac48Address address) -{ - m_address = address; -} -\endcode - -Building a topology with such a device is then a matter of -instanciating a set of SimpleNetDevice objects connected on a shared -SimpleChannel: -\code -NodeContainer nodes; -nodes.Create (10); -Ptr channel = CreateObject (); -for (uint32_t i = 0; i < nodes.GetN (); ++i) - { - CreateSimpleDevice (nodes.Get (i), channel); - } -\endcode - -With the following CreateSimpleDevice function: -\code -static Ptr -CreateSimpleDevice (Ptr node, Ptr channel) -{ - Ptr device = CreateObject (); - device->SetAddress (Mac48Address:Allocate ()); - device->SetChannel (channel); - node->AddDevice (device); - return device; -} -\endcode - -Of course, ultimately, you need to provide a helper class for this new device and channel -to save each user from having to re-implement their own CreateSimpleDevice helper -function: - -\code -class SimpleHelper -{ -public: - NetDeviceContainer Install (NodeContainer nodes, Ptr channel); - NetDeviceContainer Install (NodeContainer nodes); -}; -\endcode - -with the following straightforward implementation, inspired by the CreateSimpleDevice -function defined above: - -\code -NetDeviceContainer -SimpleHelper::Install (NodeContainer nodes, Ptr channel) -{ - NetDeviceContainer devices; - for (NodeContainer::Iterator i = nodes.Begin (); i != nodes.End (); ++i) - { - Ptr dev = CreateObject (); - dev->SetAddress (Mac48Address::Allocate ()); - dev->SetChannel (channel); - (*i)->AddDevice (dev); - devices.Add (dev); - } - return devices; -} -NetDeviceContainer -SimpleHelper::Install (NodeContainer nodes) -{ - return Install (nodes, CreateObject ()); -} -\endcode - -Of course, at some point, this device helper class should also contain a couple of -ascii and pcap tracing helper functions but, since the default SimpleNetDevice -class we used as an example here does not report any trace event, it would -be of little use. - -*/ diff --git a/doc/howtos/howtos-packet-header.h b/doc/howtos/howtos-packet-header.h deleted file mode 100644 index cf442167e..000000000 --- a/doc/howtos/howtos-packet-header.h +++ /dev/null @@ -1,119 +0,0 @@ -/*! -\page packet-header-trailer How to create a new type of protocol header or trailer -\anchor howtos-packet-header-trailer - -Question: I want to implement a new protocol X which uses a new -type of header Y. How do I implement and use this new header Y in ns-3 ? - -Answer: The key is to implement a new subclass of the ns3::Header -base class to represent your protocol header: -\code -class YHeader : public Header -{ -public: - // must be implemented to become a valid new header. - static TypeId GetTypeId (void); - virtual TypeId GetInstanceTypeId (void) const; - virtual uint32_t GetSerializedSize (void) const; - virtual void Serialize (Buffer::Iterator start) const; - virtual uint32_t Deserialize (Buffer::Iterator start); - virtual void Print (std::ostream &os) const; - - // allow protocol-specific access to the header data. - void SetData (uint32_t data); - uint32_t GetData (void) const; -private: - uint32_t m_data; -}; -\endcode - -Once this class is implemented, you can easily store your protocol -header into a packet: -\code -Ptr p = ...; -YHeader yHeader; -yHeader.SetData (0xdeadbeaf); -// copy the header into the packet -p->AddHeader (yHeader); -\endcode -and get it out of a packet: -\code -Ptr p = ...; -YHeader yHeader; -// copy the header from the packet -p->RemoveHeader (yHeader); -uint32_t data = yHeader.GetData (); -\endcode - -The implementation of the new header is very simple. First, you need -to give a TypeId to your YHeader class: -\code -TypeId -YHeader::GetTypeId (void) -{ - static TypeId tid = TypeId ("YHeader") - .SetParent
() - .AddConstructor () - ; - return tid; -} -TypeId -YHeader::GetInstanceTypeId (void) -{ - return GetTypeId (); -} -\endcode - -Then, you need to allow your header to serialize and deserialize itself -to a byte buffer in its network representation. Here, our new protocol -header contains first a 2-byte constant, and, then, the data field so, -the total size of the header is 2+4=6 bytes. -\code -uint32_t -YHeader::GetSerializedSize (void) const -{ - return 6; -} -void -YHeader::Serialize (Buffer::Iterator start) const -{ - // The 2 byte-constant - start.WriteU8 (0xfe); - start.WriteU8 (0xef); - // The data. - start.WriteHtonU32 (m_data); -} -uint32_t -YHeader::Deserialize (Buffer::Iterator start) -{ - uint8_t tmp; - tmp = start.ReadU8 (); - NS_ASSERT (tmp == 0xfe); - tmp = start.ReadU8 (); - NS_ASSERT (tmp == 0xef); - m_data = start.ReadNtohU32 (); - return 6; // the number of bytes consumed. -} -\endcode - -Finally, to make sure that Packet::Print also prints the content -of your header, just as it prints the content of the other -headers of the system, you need to provide a Print method: -\code -void -YHeader::Print (std::ostream &os) const -{ - os << "data=" << m_data; -} -\endcode - -The code will look the same if you want to implement a trailer, -that is, a protocol data structure which will be appended to the -end of the packet, not its start: you need to make sure that -you derive from the ns3::Trailer base class and that you call -Packet::AddTrailer and Packet::RemoveTrailer. Another important -detail is that you must make sure to rewind the iterator in your -Serialize and Deserialize methods writing to or reading from -the underlying buffer. - -*/ diff --git a/doc/howtos/howtos.h b/doc/howtos/howtos.h deleted file mode 100644 index 199b0d1b9..000000000 --- a/doc/howtos/howtos.h +++ /dev/null @@ -1,20 +0,0 @@ -/*! -\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: - -- User FAQ -- Developer FAQ - -Please consider contributing tips to either the wiki (yourself) or -by submitting a patch to this maintained documentation. - -- \subpage callbacks -- \subpage packet-header-trailer -- \subpage net-device -- \subpage application - -*/ - diff --git a/doc/main.h b/doc/main.h index 260438f8c..0b4a43528 100644 --- a/doc/main.h +++ b/doc/main.h @@ -15,12 +15,12 @@ * 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" * - tutorial: The ns-3 tutorial is a separate document maintained in GNU Texinfo. + * - Reference manual: The ns-3 tutorial is a separate document maintained in GNU Texinfo. + * - Testing and validation manual: The ns-3 tutorial is a separate document maintained in GNU Texinfo. * - The ns-3 wiki * contains additional user-contributed material. Some wiki-contributed - * material may migrate to and overlap with the Doxygen information. + * material may migrate to and overlap with the Doxygen and manual information. * * \section install-sec Building the Documentation *