00001 /*! 00002 \page application How to create a traffic generator ? 00003 \anchor howtos-application 00004 00005 <b>Question:</b> How do I create a new traffic generator ? 00006 00007 <b>Answer:</b> It is possible to instanciate \ref ns3::Packet "Packet" 00008 objects, schedule events, and call functions from any piece of code 00009 in ns-3 so, technically, there is no single answer to the question of 00010 how we can write a new traffic generator. However, the 00011 \ref ns3::Socket "Socket" API was really designed to be the single 00012 point of entry for traffic generators or traffic analysers and the 00013 \ref ns3::Application "Application" class was designed to hold 00014 together any number of sockets. 00015 00016 Implementing a new traffic generator thus boils down to: 00017 - implementing a new subclass of the \ref ns3::Application "Application" 00018 base class 00019 - instanciate one or many sockets within that application 00020 - start scheduling events when \ref ns3::Application::StartApplication "StartApplication" 00021 is called 00022 - stop scheduling events when \ref ns3::Application::StopApplication "StopApplication" 00023 is called 00024 - create packets and send them over one or many sockets in each event 00025 00026 The following "random" generator generates packets separated by a random 00027 delay and with a random size. 00028 00029 \code 00030 class RandomGenerator : public Application 00031 { 00032 public: 00033 RandomGenerator (); 00034 void SetDelay (RandomVariable delay); 00035 void SetSize (RandomVariable size); 00036 void SetRemote (std::string socketType, 00037 Address remote); 00038 private: 00039 virtual void StartApplication (void); 00040 virtual void StopApplication (void); 00041 void DoGenerate (void); 00042 00043 RandomVariable m_delay; 00044 RandomVariable m_size; 00045 Ptr<Socket> m_socket; 00046 }; 00047 \endcode 00048 00049 The socket is created in the SetRemote method: 00050 \code 00051 void 00052 RandomGenerator::SetRemote (std::string socketType, 00053 Address remote) 00054 { 00055 TypeId tid = TypeId::LookupByName (socketType); 00056 m_socket = Socket::CreateSocket (GetNode (), tid); 00057 m_socket->Bind (); 00058 m_socket->ShutdownRecv (); 00059 m_socket->Connect (remote); 00060 } 00061 \endcode 00062 While the the crux of the logic is located in the DoGenerate method 00063 which is called from within StartApplication: 00064 \code 00065 void 00066 RandomGenerator::DoGenerate (void) 00067 { 00068 m_next = Simulator::Schedule (Seconds (m_delay.GetValue ()), 00069 &RandomGenerator::DoGenerate, this); 00070 Ptr<Packet> p = Create<Packet> (m_size.GetIntValue ()); 00071 m_socket->Send (p); 00072 } 00073 \endcode 00074 00075 To make that application more integrated in ns-3, it needs an associated 00076 helper class: 00077 \code 00078 class RandomAppHelper 00079 { 00080 public: 00081 RandomAppHelper (std::string protocol, Address remote); 00082 void SetPacketSize (RandomVariable packetSize); 00083 void SetDelay (RandomVariable delay); 00084 ApplicationContainer Install (NodeContainer nodes); 00085 private: 00086 std::string m_protocol; 00087 Address m_remote; 00088 RandomVariable m_packetSize; 00089 RandomVariable m_delay; 00090 }; 00091 \endcode 00092 00093 which could be trivially implemented as: 00094 \code 00095 ApplicationContainer 00096 RandomAppHelper::Install (NodeContainer nodes) 00097 { 00098 ApplicationContainer applications; 00099 for (NodeContainer::Iterator i = nodes.Begin (); i != nodes.End (); ++i) 00100 { 00101 Ptr<RandomAppHelper> app = CreateObject<RandomAppHelper> (); 00102 app->SetSize (m_packetSize); 00103 app->SetDelay (m_delay); 00104 app->SetRemote (m_protocol, m_remote); 00105 (*i)->AddApplication (app); 00106 applications.Add (app); 00107 } 00108 return applications; 00109 } 00110 \endcode 00111 00112 Despite being functional, this API is not very consistant with the style of 00113 the other helper classes, all of which allow you to control the parameters 00114 of the underlying class through attributes and not explicit setters. The 00115 following API thus replaces the pair SetPacketSize/SetDelay with a single 00116 method SetAttribute: 00117 \code 00118 class RandomAppHelper 00119 { 00120 public: 00121 RandomAppHelper (std::string protocol, Address remote); 00122 void SetAttribute (std::string name, const AttributeValue &value); 00123 ApplicationContainer Install (NodeContainer c); 00124 private: 00125 std::string m_protocol; 00126 Address m_remote; 00127 ObjectFactory m_factory; 00128 }; 00129 \endcode 00130 00131 And which can be used as follows: 00132 \code 00133 RandomAppHelper app = RandomAppHelper ("ns3::TcpSocketFactory", 00134 InetSocketAddress (Ipv4Address ("192.168.1.10"), 10)); 00135 app.SetAttribute ("Delay", StringValue ("Constant:2.5")); 00136 app.SetAttribute ("Size", StringValue ("Constant:2100")); 00137 app.Install (nodes); 00138 \endcode 00139 00140 The implementation, in this case, is not necessarily longer but its 00141 simplicity hides a lot of behind-the-scenes complexity: 00142 00143 \code 00144 void 00145 RandomAppHelper::SetAttribute (std::string name, const AttributeValue &value) 00146 { 00147 m_factory.Set (name, value); 00148 } 00149 ApplicationContainer 00150 RandomAppHelper::Install (NodeContainer nodes) 00151 { 00152 ApplicationContainer applications; 00153 for (NodeContainer::Iterator i = nodes.Begin (); i != nodes.End (); ++i) 00154 { 00155 Ptr<RandomAppHelper> app = m_factory.Create<RandomAppHelper> (); 00156 app->SetRemote (m_socketType, m_remote); 00157 (*i)->AddApplication (app); 00158 applications.Add (app); 00159 } 00160 return applications; 00161 } 00162 \endcode 00163 00164 The key difference between this implementation and the previous one 00165 is that this helper does not handle explicitely the attributes 00166 delay and packet size. Instead, it stores them in an 00167 \ref ns3::ObjectFactory "ObjectFactory" object. This, of course, 00168 does not work magically, and requires extra support from the 00169 underlying RandomGenerator class. Specifically, it requires 00170 that the underlying RandomGenerator defines its attributes 00171 in its \ref ns3::TypeId "TypeId" in a new public static method: 00172 00173 \code 00174 class RandomGenerator 00175 { 00176 public: 00177 static TypeId GetTypeId (void); 00178 }; 00179 \endcode 00180 00181 The corresponding implementation is shown below: 00182 00183 \code 00184 TypeId 00185 RandomGenerator::GetTypeId (void) 00186 { 00187 static TypeId tid = TypeId ("RandomGenerator") 00188 .SetParent<Application> () 00189 .AddConstructor<RandomGenerator> () 00190 .AddAttribute ("Delay", "The delay between two packets (s)", 00191 RandomVariableValue (ConstantVariable (1.0)), 00192 MakeRandomVariableAccessor (&RandomGenerator::m_delay), 00193 MakeRandomVariableChecker ()) 00194 .AddAttribute ("PacketSize", "The size of each packet (bytes)", 00195 RandomVariableValue (ConstantVariable (2000)), 00196 MakeRandomVariableAccessor (&RandomGenerator::m_size), 00197 MakeRandomVariableChecker ()) 00198 ; 00199 return tid; 00200 } 00201 \endcode 00202 00203 */