Add doclib/fix-links.py to temporarily fix/remove bad doxygen links
[senf.git] / PPI / Mainpage.dox
1 // Copyright (C) 2007 
2 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
3 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
4 //     Stefan Bund <g0dil@berlios.de>
5 //
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the
18 // Free Software Foundation, Inc.,
19 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20
21 /** \mainpage libPPI : The Packet Processing Infrastructure
22
23     The PPI provides an infrastructure to create packet oriented network processing applications. A
24     PPI application is built by combining processing modules in a very flexible manner.
25
26     \image html scenario.png Target Scenario
27     
28     The PPI concept is built around some key concepts
29
30     \li The PPI is based on processing \ref packets. It does not handle stream oriented channels.
31     \li The PPI is built around reusable \ref modules. Each module is completely independent.
32     \li Each module has an arbitrary number of \ref connectors, inputs and outputs.
33     \li The modules are connected to each other using flexible \ref connections.
34     \li Data flow throughout the network is governed via flexible automatic or manual \ref
35         throttling.
36     \li Modules may register additional external \ref events (file descriptor events or timers).
37     
38     The PPI thereby builds on the facilities provided by the other components of the SENF
39     framework. The target scenario above depicts a diffserv capable UDLR/ULE router including
40     performance optimizations for TCP traffic (PEP). This router is built by combining several
41     modules.
42
43     \see \ref overview \n
44         <a href="../../../Examples/RateStuffer/doc/html/index.html">PPI Example Application:
45         RateStuffer</a> \n
46         \ref senf::ppi::module "Modules" \n
47         \ref senf::ppi::connector "Connectors" \n
48         \ref event_group
49  */
50
51 /** \page overview PPI Overview and Concepts
52
53     \section design Design considerations
54
55     The PPI interface is designed to be as simple as possible. It provides sane defaults for all
56     configurable parameters to simplify getting started. It also automates all resource
57     management. The throttling infrastructure handles blocking conditions (like input exhaustion)
58     automatically 
59
60     \section packets Packets
61
62     The PPI processes packets and uses the <a href="@TOPDIR@/Packets/doc/html/index.html">Packet
63     library</a> to handle them. All packets are passed around as generic Packet::ptr's, the PPI
64     does not enforce any packet type restrictions.
65
66     \section modules Modules
67
68     A module is represented by a class type. Each module has several components:
69
70     \li It may have any number of connectors (inputs and outputs)
71     \li Each module declares flow information which details the route packets take within the
72         module. This information does not define how the information is processed, it only tells,
73         where data arriving on some input will be directed at.
74     \li The module might take additional parameters.
75     \li The module might also register additional events.
76
77     Modules are divided roughly in to two categories: I/O modules provide packet sources and sinks
78     (network connection, writing packets to disk, generating new packets) whereas processing modules
79     process packets internally.  In the target scenario, <em>TAP</em>, <em>ASI Out</em>, <em>Raw
80     Socket</em> and in a limited way <em>Generator</em> are I/O modules whereas <em>PEP</em>,
81     <em>DiffServ</em>, <em>DVB Enc</em>, <em>GRE/UDLR</em>, <em>TCP Filter</em> and <em>Stuffer</em>
82     are processing modules. <em>ASI/MPEG</em> and <em>Net</em> are external I/O ports which are
83     integrated via the <em>TAP</em>, <em>ASI Out</em> and <em>Raw Sock</em> modules using external
84     events.
85
86     The following example module declares three I/O connectors (see below): <tt>payload</tt>,
87     <tt>stuffing</tt> and <tt>output</tt>. These connectors are defined as <em>public</em> data
88     members so they can be accessed from the outside. This is important as we will see below.
89
90     \code
91       class RateStuffer
92           : public senf::ppi::module::Module
93       {
94           senf::ppi::IntervalTimer timer_;
95
96       public:
97           senf::ppi::connector::ActiveInput payload;
98           senf::ppi::connector::ActiveInput stuffing;
99           senf::ppi::connector::ActiveOutput output;
100
101           RateStuffer(unsigned packetsPerSecond)
102               : timer_(1000u, packetsPerSecond)
103           {
104               route(payload, output);
105               route(stuffing, output);
106
107               registerEvent(&RateStuffer::tick, timer_);
108           }
109
110       private:
111           void tick()
112           {
113               if (payload)
114                   output(payload());
115               else
116                   output(stuffing());
117           }
118       };
119     \endcode
120
121     On module instantiation, it will declare it's flow information with <tt>route</tt> (which is
122     inherited from <tt>senf::ppi::module::Module</tt>). Then the module registers an interval timer
123     which will fire <tt>packetsPerSecond</tt> times every <tt>1000</tt> milliseconds.
124
125     The processing of the module is very simple: Whenever a timer tick arrives a packet is sent. If
126     the <tt>payload</tt> input is ready (see throttling below), a payload packet is sent, otherwise
127     a stuffing packet is sent. The module will therefore provide a constant stream of packets at a
128     fixed rate on <tt>output</tt>
129     
130     An example module to generate the stuffing packets could be
131
132     \code
133       class CopyPacketGenerator
134           : public senf::ppi::module::Module
135       {
136       public:
137           senf::ppi::connector::PassiveOutput output;
138
139           CopyPacketGenerator(Packet::ptr template)
140               : template_ (template)
141           {
142               noroute(output);
143               output.onRequest(&CopyPacketGenerator::makePacket);
144           }
145
146       private:
147           Packet::ptr template_;
148
149           void makePacket()
150           {
151               output(template_.clone());
152           }
153       };
154     \endcode
155
156     This module just produces a copy of a given packet whenever output is requested.
157
158     \section connectors Connectors
159     
160     Inputs and Outputs can be active and passive. An \e active I/O is <em>activated by the
161     module</em> to send data or to poll for available packets. A \e passive I/O is <em>signaled by
162     the framework</em> to fetch data from the module or to pass data into the module.
163
164     To send or receive a packet (either actively or after packet reception has been signaled), the
165     module just calls the connector. This allows to generate or process multiple packets in one
166     iteration. However, reading will only succeed, as long as packets are available from the
167     connection.
168
169     Since a module is free to generate more than a single packet on incoming packet requests, all
170     input connectors incorporate a packet queue. This queue is exposed to the module and allows the
171     module to process packets in batches.
172
173     \section connections Connections
174
175     \image html ratestuffer.png Simple RateStuffer
176
177     To make use of the modules, they have to be instantiated and connections have to be created
178     between the I/O connectors. It is possible to connect any pair of input/output connectors as
179     long as one of them is active and the other is passive.
180     
181     It is possible to connect two active connectors with each other using a special adaptor
182     module. This Module has a passive input and a passive output. It will queue any incoming packets
183     and automatically handle throttling events (see below). This adaptor is automatically added by
184     the connect method if needed.
185
186     To complete our simplified example: Lets say we have an <tt>ActiveSocketInput</tt> and a
187     <tt>PassiveUdpOutput</tt> module. We can then use our <tt>RateStuffer</tt> module to build an
188     application which will create a fixed-rate UDP stream:
189
190     \code
191       RateStuffer rateStuffer (10);
192
193       senf::Packet::ptr stuffingPacket = senf::Packet::create<...>(...); 
194       CopyPacketGenerator generator (stuffingPacket);
195
196       senf::UDPv4ClientSocketHandle inputSocket (1111);
197       senf::ppi::module::ActiveSocketReader udpInput (inputSocket);
198
199       senf::UDPv4ClientSocketHandle outputSocket ("2.3.4.5:2222");
200       senf::ppi::module::PassiveSocketWriter udpOutput (outputSocket);
201
202       senf::ppi::module::PassiveQueue adaptor;
203
204       senf::ppi::connect(udpInput.output, adaptor.input);
205       senf::ppi::connect(adaptor.output, rateStuffer.payload);
206       adaptor.qdisc(ThresholdQueueing(10,5));
207       senf::ppi::connect(generator.output, rateStuffer.stuffing);
208       senf::ppi::connect(rateStuffer.output, udpOutput.input);
209
210       senf::ppi::run();
211     \endcode
212
213     First all necessary modules are created. Then the connections between these modules are set
214     up. The buffering on the udpInput <-> rateStuffer adaptor is changed so the queue will begin to
215     throttle only if more than 10 packets are in the queue. The connection will be unthrottled as
216     soon as there are no more than 5 packets left in the queue. This application will read
217     udp-packets coming in on port 1111 and will forward them to port 2222 on host 2.3.4.5 with a
218     fixed rate of 10 packets / second.
219
220     \section throttling Throttling
221
222     If a passive connector cannot handle incoming requests, this connector may be \e
223     throttled. Throttling a request will forward a throttle notification to the module connected
224     to that connector. The module then must handle this throttle notification. If automatic
225     throttling is enabled for the module (which is the default), the notification will automatically
226     be forwarded to all dependent connectors as taken from the flow information. For there it will
227     be forwarded to further modules and so on.
228
229     A throttle notification reaching an I/O module will normally disable the input/output by
230     disabling any external I/O events registered by the module. When the passive connector which
231     originated the notification becomes active again, it creates an unthrottle notification which
232     will be forwarded in the same way. This notification will re-enable any registered I/O events.
233
234     The above discussion shows, that throttle events are always generated on passive connectors and
235     received on active connectors. To differentiate further, the throttling originating from a
236     passive input is called <em>backward throttling</em> since it is forwarded in the direction \e
237     opposite to the data flow. Backward throttling notifications are sent towards the input
238     modules. On the other hand, the throttling originating from a passive output is called
239     <em>forward throttling</em> since it is forwarded along the \e same direction the data
240     is. Forward throttling notifications are therefore sent towards the output modules.
241
242     Since throttling a passive input may not disable all further packet delivery immediately, all
243     inputs contains an input queue. In it's default configuration, the queue will send out throttle
244     notifications when it becomes non-empty and unthrottle notifications when it becomes empty
245     again. This automatic behavior may however be disabled. This allows a module to collect incoming
246     packets in it's input queue before processing a bunch of them in one go.
247
248     \section events Events
249
250     Modules may register additional events. These external events are very important since they
251     drive the PPI framework. Possible event sources are
252     \li time based events
253     \li file descriptors.
254     \li internal events (e.g. IdleEvent)
255
256     Here some example code implementing the ActiveSocketInput Module:
257
258     \code
259       class ActiveSocketReader
260           : public senf::ppi::module::Module
261       {
262           typedef senf::ClientSocketHandle<
263               senf::MakeSocketPolicy< senf::ReadablePolicy,
264                                       senf::DatagramFramingPolicy > > SocketHandle;
265           SocketHandle socket_;
266           DataParser const & parser_;
267           senf::ppi:IOSignaler event_;
268
269           static PacketParser<senf::DataPacket> defaultParser_;
270
271       public:
272           senf::ppi::connector::ActiveOutput output;
273
274           // I hestitate taking parser by const & since a const & can be bound to
275           // a temporary even though a const & is all we need. The real implementation
276           // will probably make this a template arg. This simplifies the memory management
277           // from the users pov.
278           ActiveSocketReader(SocketHandle socket, 
279                              DataParser & parser = ActiveSocketReader::defaultParser_)
280               : socket_ (socket), 
281                 parser_ (parser)
282                 event_ (socket, senf::ppi::IOSignaler::Read)
283           {
284               registerEvent( &ActiveSocketReader::data, event_ );
285               route(event_, output);
286           }
287       
288       private:
289     
290           void data()
291           {
292               std::string data;
293               socket_.read(data);
294               output(parser_(data));
295           }
296       };
297     \endcode
298
299     First we declare our own socket handle type which allows us to read packets. The constructor
300     then takes two arguments: A compatible socket and a parser object. This parser object gets
301     passed the packet data as read from the socket (an \c std::string) and returns a
302     senf::Packet::ptr. The \c PacketParser is a simple parser which interprets the data as specified
303     by the template argument.
304
305     We register an IOSignaler event. This event will be signaled whenever the socket is
306     readable. This event is routed to the output. This routing automates throttling for the socket:
307     Whenever the output receives a throttle notifications, the event will be temporarily disabled.
308
309     Processing arriving packets happens in the \c data() member: This member simple reads a packet
310     from the socket. It passes this packet to the \c parser_ and sends the generated packet out.
311
312     \section flows Information Flow
313
314     The above description conceptually introduces three different flow levels:
315      
316     \li The <em>data flow</em> is, where the packets are flowing. This flow always goes from output
317         to input connector.
318     \li The <em>execution flow</em> describes the flow of execution from one module to another. This
319         flow always proceeds from active to passive connector.
320     \li The <em>control flow</em> is the flow of throttling notifications. This flow always proceeds
321         \e opposite to the execution flow, from passive to active connector.
322
323     This is the outside view, from without any module. These flows are set up using
324     senf::ppi::connect() statements.
325
326     Within a module, the different flow levels are defined differently depending on the type of
327     flow:
328     
329     \li The <em>data flow</em> is defined by how data is processed. The different event and
330         connector callbacks will pass packets around and thereby define the data flow
331     \li Likewise, the <em>execution flow</em> is defined parallel to the data flow (however possible
332         in opposite direction) by how the handler of one connector calls other connectors.
333     \li The <em>control flow</em> is set up using senf::ppi::Module::route statements (as long as
334         automatic throttling is used. Manual throttling defines the control flow within the
335         respective callbacks).
336
337     In nearly all cases, these flows will be parallel. Therefore it makes sense to define the \c
338     route statement as defining the 'conceptual data flow' since this is also how control messages
339     should flow (sans the direction, which is defined by the connectors active/passive property).
340
341     \see \ref ppi_implementation
342  */
343
344 /** \page ppi_implementation Implementation Notes
345     
346     \section processing Data Processing
347
348     The processing in the PPI is driven by events. Without events <em>nothing will happen</em>. When
349     an event is generated, the called module will probably call one of it's active connectors.
350
351     Calling an active connector will directly call the handler registered at the connected passive
352     connector. This way the call and data are handed across the connections until an I/O module will
353     finally handle the request (by not calling any other connectors).
354
355     Throttling is handled in the same way: Throttling a passive connector will call a corresponding
356     (internal) method of the connected active connector. This method will call registered handlers
357     and will analyze the routing information of the module for other (passive) connectors to call
358     and throttle. This will again create a call chain which terminates at the I/O modules. An event
359     which is called to be throttled will disable the event temporarily. Unthrottling works in the
360     same way.
361
362     This simple structure is complicated by the existence of the input queues. This affects both
363     data forwarding and throttling:
364     \li A data request will only be forwarded, if no data is available in the queue
365     \li The connection will only be throttled when the queue is empty
366     \li Handlers of passive input connectors must be called repeatedly until either the queue is
367         empty or the handler does not take any packets from the queue
368
369
370     \section logistics Managing the Data Structures
371
372     The PPI itself is a singleton. This simplifies many of the interfaces (We do not need to pass
373     the PPI instance). Should it be necessary to have several PPI systems working in parallel
374     (either by registering all events with the same event handler or by utilizing multiple threads),
375     we can still extend the API by adding an optional PPI instance argument.
376
377     Every module manages a collection of all it's connectors and every connector has a reference to
378     it's containing module. In addition, every connector maintains a collection of all it's routing
379     targets. 
380
381     All this data is initialized via the routing statements. This is, why \e every connector must
382     appear in at least one routing statement: These statements will as a side effect initialize the
383     connector with it's containing module.
384
385     Since all access to the PPI via the module is via it's base class, unbound member function
386     pointers can be provided as handler arguments: They will automatically be bound to the current
387     instance. This simplifies the PPI usage considerably. The same is true for the connectors: Since
388     they know the containing module, they can explicitly bind unbound member function pointers to
389     the instance.
390     
391
392     \section random_notes Random implementation notes
393     
394     Generation of throttle notifications: Backward throttling notifications are automatically
395     generated (if this is not disabled) whenever the input queue is non-empty \e after the event
396     handler has finished processing. Forward throttling notifications are not generated
397     automatically within the connector. However, the Passive-Passive adaptor will generate
398     Forward-throttling notifications whenever the input queue is empty.
399
400     \section class_diagram Class Diagram
401
402     \image html classes.png
403  */
404
405 \f
406 // Local Variables:
407 // mode: c++
408 // fill-column: 100
409 // c-file-style: "senf"
410 // indent-tabs-mode: nil
411 // ispell-local-dictionary: "american"
412 // mode: flyspell
413 // mode: auto-fill
414 // End:
415