forgot to add default tip
authorMathieu Lacage <mathieu.lacage@sophia.inria.fr>
Fri, 21 Aug 2009 14:04:25 +0200
changeset 17 e1b57dda1b2a
parent 16 94d7c3acd9fc
forgot to add
object-model.tex
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/object-model.tex	Fri Aug 21 14:04:25 2009 +0200
@@ -0,0 +1,537 @@
+
+\begin{frame}{It's easy to build a network simulator}
+
+It's just a matter of:
+\begin{itemize}
+\item Provide an event scheduler
+\item Implement a couple of models to create and consume events
+\end{itemize}
+
+But it's much harder to build a network simulator
+which:
+\begin{itemize}
+\item Allows models to be reusable independently
+\item Ensures API coherence between models
+\item Automates common tasks (tracing, configuration)
+\end{itemize}
+
+\end{frame}
+
+\begin{section}{A coherent memory management scheme}
+
+\begin{frame}[fragile]{Why are objects so complicated to create ?}
+We do:
+\begin{block}{}
+\begin{verbatim}
+  Ptr<Node> node0 = CreateObject<Node> ();
+\end{verbatim}
+\end{block}
+Why not:
+\begin{block}{}
+\begin{verbatim}
+  Node *node0 = new Node ();
+\end{verbatim}
+\end{block}
+Or:
+\begin{block}{}
+\begin{verbatim}
+  Node node0 = Node ();
+\end{verbatim}
+\end{block}
+\end{frame}
+
+\begin{frame}{Templates: the Nasty Brackets}
+\begin{itemize}
+\item Contain a list of \emph{type} arguments
+\item Parameterize a class or function from input type
+\item In ns-3, used for:
+\begin{itemize}
+\item Standard Template Library
+\item Syntactical sugar for low-level facilities
+\end{itemize}
+\item Saves a lot of typing
+\item No portability/compiler support problem
+\item Sometimes painful to decipher error messages.
+\end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]{Memory Management}
+It is hard in C++:
+\begin{itemize}
+\item No garbage collector
+\item Easy to forget to delete an object
+\item Pointer cycles
+\item Ensure coherency and uniformity
+\end{itemize}
+So, we use:
+\begin{itemize}
+\item Reference counting: track number of pointers
+to an object (\code{Ref}+\code{Unref})
+\item Smart pointers: \code{Ptr<>}, \code{Create<>} and, \code{CreateObject<>}
+\item Sometimes, explicit \code{Dispose} to break cycles
+\end{itemize}
+
+\end{frame}
+
+\end{section}
+
+\begin{section}{Maximizing model reuse}
+
+\begin{frame}[fragile]{Where is my MobileNode ?}
+
+\begin{block}{}
+\begin{verbatim}
+Ptr<Node> node = CreateObject<Node> ();
+Ptr<MobilityModel> mobility = CreateObject<...> ();
+node->AggregateObject (mobility);
+\end{verbatim}
+\end{block}
+
+\begin{itemize}
+\item Some nodes need an IPv4 stack, a position, an energy model. 
+\item Some nodes need just two out of three. 
+\item Others need other unknown features.
+\item The obvious solution: add everything to the Node base class:
+\begin{itemize}
+\item The class will grow uncontrollably over time
+\item Everyone will need to patch the class
+\item Slowly, every piece of code will depend on every other piece of code 
+(cannot reuse anything without dragging in everything)
+\item A maintenance nightmare...
+\end{itemize}
+\item A better solution:
+\begin{itemize}
+\item Separate functionality belongs to separate classes
+\item Objects can be aggregated at runtime to obtain extra functionality
+\end{itemize}
+\end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]{Object aggregation}
+
+\begin{columns}[T]
+\begin{column}{0.4\textwidth}
+\includegraphics[width=9cm]{object-aggregation}
+\end{column}
+\begin{column}{0.6\textwidth}
+\begin{itemize}
+\item A circular singly linked-list
+\item AggregateObject is a constant-time operation
+\item GetObject is a O(n) operation
+\item Aggregate contains only one object of each type
+\end{itemize}
+\end{column}
+\end{columns}
+\end{frame}
+
+\end{section}
+
+\begin{section}{Getting the right object}
+
+\begin{frame}[fragile]{The traditional approach}
+
+In C++, if you want to call methods on an object, you need a
+pointer to this object. To get a pointer, you need to:
+\begin{itemize}
+\item keep local copies of pointers to every object you create
+\item walk pointer chains to get access to objects created within other objects
+\end{itemize}
+
+For example, in ns-3, you could do this:
+\begin{block}{}
+\begin{verbatim}
+Ptr<NetDevice> dev = NodeList::Get (5)->GetDevice (0);
+Ptr<WifiNetDevice> wifi = dev->GetObject<WifiNetDevice> ();
+Ptr<WifiPhy> phy = dev->GetPhy ();
+phy->SetAttribute ("TxGain", ...);
+phy->ConnectTraceSource (...);
+\end{verbatim}
+\end{block}
+It's not fun to do...
+\end{frame}
+
+\begin{frame}[fragile]{Use a namespace string !}
+
+Set an attribute:
+\begin{block}{}
+\begin{verbatim}
+Config::SetAttribute ("/NodeList/5/DeviceList/0/Phy/TxGain", 
+                      StringValue ("10"));
+\end{verbatim}
+\end{block}
+Connect a trace sink to a trace source:
+\begin{block}{}
+\begin{verbatim}
+Config::Connect ("/NodeList/5/DeviceList/0/Phy/TxGain", 
+                 MakeCallback (&LocalSink));
+\end{verbatim}
+\end{block}
+Just get a pointer:
+\begin{block}{}
+\begin{verbatim}
+Config::MatchContainer match;
+match = Config::LookupMatches ("/NodeList/5/DeviceList/0/Phy/");
+Ptr<WifiPhy> phy = match.Get (0)->GetObject<WifiPhy> ();
+\end{verbatim}
+\end{block}
+
+\end{frame}
+
+\begin{frame}[allowframebreaks]{The object namespace}
+
+Object namespace strings represent a path
+through a set of object pointers:
+\\
+\vspace{1em}
+\includegraphics[width=6cm]{attribute-namespace}
+\\
+For example, \code{/NodeList/x/DeviceList/y/InterframeGap}
+represents the \code{InterframeGap} attribute of the device
+number \emph{y} in node number \emph{x}.
+
+\break
+
+Navigating the attributes using paths:
+\begin{itemize}
+\item \code{/NodeList/[3-5]|8|[0-1]}: matches nodes index 0, 1, 3, 4, 5, 8
+\item \code{/NodeList/*}: matches all nodes
+\item \code{/NodeList/3/\$ns3::Ipv4}: matches object of type 
+\code{ns3::Ipv4} aggregated to node number 3
+\item \code{/NodeList/3/DeviceList/*/\$ns3::CsmaNetDevice}: matches 
+all devices of type \code{ns3::CsmaNetDevice} within node number 3
+\item \code{/NodeList/3/DeviceList/0/RemoteStationManager}: matches 
+the object pointed to by attribute RemoteStationManager
+in device 0 in node 3.
+\end{itemize}
+
+\end{frame}
+
+\end{section}
+
+\begin{section}{A uniform configuration system}
+
+\begin{frame}[fragile]{Traditionally, in C++}
+
+\begin{itemize}
+\item Export attributes as part of a class's public API
+\item Use static variables for defaults
+\end{itemize}
+For example:
+{\footnotesize
+\begin{block}{}
+\begin{verbatim}
+class MyModel {
+public:
+  MyModel () : m_foo (m_defaultFoo) {}
+  void SetFoo (int foo) {m_foo = foo;}
+  int GetFoo (void) {return m_foo}
+  static void SetDefaultFoo (int foo) {m_defaultFoo = foo;}
+  static int GetDefaultFoo (void) {return m_defaultFoo;}
+private:
+  int m_foo;
+  static int m_defaultFoo = 10;
+};
+\end{verbatim}
+\end{block}
+}
+
+\end{frame}
+
+\begin{frame}[fragile,allowframebreaks]{In ns-3, done automatically}
+
+\begin{itemize}
+\item Set a default value:
+{\footnotesize
+\begin{block}{}
+\begin{verbatim}
+Config::SetDefaultValue ("ns3::WifiPhy::TxGain", StringValue ("10"));
+\end{verbatim}
+\end{block}
+}
+\item Set a value on a specific object:
+{\footnotesize
+\begin{block}{}
+\begin{verbatim}
+phy->SetAttribute ("TxGain", StringValue ("10"));
+\end{verbatim}
+\end{block}
+}
+\item Set a value from the command-line \code{--ns3::WifiPhy::TxGain=10}:
+{\footnotesize
+\begin{block}{}
+\begin{verbatim}
+CommandLine cmd;
+cmd.Parse (argc, argv);
+\end{verbatim}
+\end{block}
+}
+\end{itemize}
+
+\break
+
+\begin{itemize}
+\item Load, Change, and Save all values from and to a raw text or xml file 
+with or without a GUI:
+{\footnotesize
+\begin{block}{}
+\begin{verbatim}
+GtkConfigStore config;
+config.ConfigureDefaults ();
+...
+config.ConfigureAttributes ();
+\end{verbatim}
+\end{block}
+}
+\item Set a value with an environment variable 
+\code{NS\_ATTRIBUTE\_DEFAULT=ns3::WifiPhy::TxGain=10}
+\end{itemize}
+
+\end{frame}
+
+\begin{frame}{Graphical navigation}
+
+\includegraphics[width=5cm]{gtk-config-store}
+
+\end{frame}
+
+\begin{frame}{Doxygen documentation}
+
+\includegraphics[width=10cm]{attribute-doxygen}
+
+\end{frame}
+
+\end{section}
+
+\begin{section}{Controlling trace output format}
+
+\begin{frame}[fragile]{Tracing requirements}
+
+\begin{itemize}
+\item Tracing is a structured form of simulation output
+\item Example (from ns-2):
+\begin{verbatim}
++ 1.84375 0 2 cbr 210 ------- 0 0.0 3.1 225 610
+- 1.84375 0 2 cbr 210 ------- 0 0.0 3.1 225 610
+r 1.84471 2 1 cbr 210 ------- 1 3.0 1.0 195 600
+r 1.84566 2 0 ack 40 ------- 2 3.2 0.1 82 602
++ 1.84566 0 2 tcp 1000 ------- 2 0.1 3.2 102 611
+\end{verbatim}
+\item Problem: tracing needs vary widely
+\begin{itemize}
+\item Would like to change tracing output format without
+editing the core
+\item Would like to support multiple output formats
+\end{itemize}
+\end{itemize}
+
+\end{frame}
+
+\begin{frame}{Tracing overview}
+
+\begin{itemize}
+\item Simulator provides a set of pre-configured
+  trace sources
+\begin{itemize}
+\item Users may edit the core to add their own
+\end{itemize}
+\item Users provide trace sinks and attach to the
+  trace source
+\begin{itemize}
+\item Simulator core provides a few examples for
+     common cases
+\end{itemize}
+\item Multiple trace sources can connect to a
+  trace sink
+\end{itemize}
+
+\end{frame}
+
+\begin{frame}{The ns-3 tracing model}
+
+Decouple trace sources from trace sinks:
+\\
+\vspace{1cm}
+\includegraphics[width=9cm]{trace-source-sink}
+\\
+\vspace{1cm}
+Benefit: Customizable trace sinks
+
+\end{frame}
+
+\begin{frame}{Ns-3 trace sources}
+
+\begin{itemize}
+\item Various trace sources (e.g., packet receptions, state
+  machine transitions) are plumbed through the system
+\item Organized with the rest of the attribute system
+\end{itemize}
+
+\includegraphics[width=9cm]{trace-source-doxygen}
+
+\end{frame}
+
+\begin{frame}{Multiple levels of tracing}
+
+\begin{itemize}
+\item High-level: use a helper to hook
+a predefined trace sink to a trace source and
+generate simple tracing output (ascii, pcap)
+\item Mid-level: hook a special trace sink
+to an existing trace source to generate
+adhoc tracing
+\item Low-level: add a new trace source
+and connect it to a special trace sink
+\end{itemize}
+
+\end{frame}
+
+\begin{frame}[fragile]{High-level tracing}
+
+\begin{itemize}
+\item Use predefined trace sinks in helpers
+\item All helpers provide ascii and pcap trace sinks
+\end{itemize}
+{\footnotesize
+\begin{block}{}
+\begin{verbatim}
+CsmaHelper::EnablePcap ("filename", nodeid, deviceid);
+std::ofstream os;
+os.open ("filename.tr");
+CsmaHelper::EnableAscii (os, nodeid, deviceid);
+\end{verbatim}
+\end{block}
+}
+
+\end{frame}
+
+\begin{frame}[fragile]{Mid-level tracing}
+
+\begin{itemize}
+\item Provide a new trace sink
+\item Use attribute/trace namespace to connect trace sink and source
+\end{itemize}
+
+{\footnotesize
+\begin{block}{}
+\begin{verbatim}
+void
+DevTxTrace (std::string context, 
+            Ptr<const Packet> p, Mac48Address address)
+{
+  std::cout << " TX to=" << address << " p: " << *p << std::endl;
+}
+Config::Connect ("/NodeList/*/DeviceList/*/Mac/MacTx", 
+                 MakeCallback (&DevTxTrace));
+\end{verbatim}
+\end{block}
+}
+
+\end{frame}
+
+\begin{frame}[fragile]{Pcap output}
+
+The trace sink:
+{\footnotesize
+\begin{block}{}
+\begin{verbatim}
+static void PcapSnifferEvent (Ptr<PcapWriter> writer, 
+                              Ptr<const Packet> packet)
+{
+  writer->WritePacket (packet);
+}
+\end{verbatim}
+\end{block}
+}
+
+Prepare the pcap output:
+{\footnotesize
+\begin{block}{}
+\begin{verbatim}
+oss << filename << "-" << nodeid << "-" << deviceid << ".pcap";
+Ptr<PcapWriter> pcap = ::ns3::Create<PcapWriter> ();
+pcap->Open (oss.str ());
+pcap->WriteWifiHeader ();
+\end{verbatim}
+\end{block}
+}
+
+Finally, connect the trace sink to the trace source:
+{\footnotesize
+\begin{block}{}
+\begin{verbatim}
+oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid;
+oss << "/$ns3::WifiNetDevice/Phy/PromiscSniffer";
+Config::ConnectWithoutContext (oss.str (), 
+                MakeBoundCallback (&PcapSnifferEvent, pcap));
+\end{verbatim}
+\end{block}
+}
+
+\end{frame}
+
+\end{section}
+
+\begin{section}{The underlying type metadata database}
+
+\begin{frame}{The ns-3 type system}
+
+\begin{itemize}
+\item The aggregation mechanism needs information about
+the type of objects at runtime
+\item The attribute mechanism needs information about the
+attributes supported by a specific object
+\item The tracing mechanism needs information about the
+trace sources supported by a specific object
+\end{itemize}
+All this information is stored in \code{ns3::TypeId}:
+\begin{itemize}
+\item The parent type
+\item The name of the type
+\item The list of attributes (their name, their type, etc.)
+\item The list of trace sources (their name, their type, etc.)
+\end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]{The ns-3 type system}
+
+It is not very complicated to use:
+\begin{itemize}
+\item Derive from the \code{ns3::Object} base class
+\item Define a \code{GetTypeId} static method:
+\begin{block}{}
+\begin{verbatim}
+class Foo : public Object {
+public:
+  static TypeId GetTypeId (void);
+};
+\end{verbatim}
+\end{block}
+\item Define the features of your object:
+\begin{block}{}
+\begin{verbatim}
+  static TypeId tid = TypeId ("ns3::Foo")
+    .SetParent<Object> ()
+    .AddAttribute ("Name", "Help", ...)
+    .AddTraceSource ("Name", "Help", ...);
+  return tid;
+\end{verbatim}
+\end{block}
+\item call \code{NS\_OBJECT\_ENSURE\_REGISTERED}
+\end{itemize}
+\end{frame}
+
+\end{section}
+
+
+\begin{frame}{Summary}
+
+\begin{itemize}
+\item Memory management is uniform and simple\pause
+\item Dynamic aggregation makes models easier to reuse\pause
+\item Path strings allow access to every object in a simulation\pause
+\item Attributes allow powerful and uniform configuration\pause
+\item Trace sources allow arbitrary output file formats\pause
+\end{itemize}
+
+\end{frame}
+