cd3167e7a9b2ee96a67b9ede86b544977e70621b
[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 ppi_packets. It does not handle stream oriented
31         channels.
32     \li The PPI is built around reusable \ref ppi_modules. Each module is completely independent.
33     \li Each module has an arbitrary number of \ref ppi_connectors, inputs and outputs.
34     \li The modules are connected to each other using flexible \ref ppi_connections.
35     \li Data flow throughout the network is governed via flexible automatic or manual \ref
36         ppi_throttling (throttle notifications).
37     \li Modules may register additional external \ref ppi_events (file descriptor events or timers).
38     
39     The PPI thereby builds on the facilities provided by the other components of the SENF
40     framework. The target scenario above depicts a diffserv capable UDLR/ULE router including
41     performance optimizations for TCP traffic (PEP). This router is built by combining several
42     modules.
43
44     \see \ref ppi_overview \n
45         <a href="../../../Examples/RateStuffer/doc/html/index.html">PPI Example Application:
46         RateStuffer</a> \n
47         \ref senf::ppi::module "Modules" \n
48         \ref senf::ppi::connector "Connectors" \n
49         \ref event_group
50  */
51
52 /** \page ppi_overview PPI Overview and Concepts
53
54     <div class="toc">
55     <div>Contents</div>
56     <ol>
57     <li>\ref ppi_design</li>
58     <li>\ref ppi_packets</li>
59     <li>\ref ppi_modules</li>
60     <li>\ref ppi_connectors</li>
61     <li>\ref ppi_connections</li>
62     <li>\ref ppi_throttling</li>
63     <li>\ref ppi_events</li>
64     <li>\ref ppi_flows</li>
65     </ol>
66     </div>
67
68     \section ppi_design Design considerations
69
70     The PPI interface is designed to be as simple as possible. It provides sane defaults for all
71     configurable parameters to simplify getting started. It also automates all resource
72     management. The throttling infrastructure handles blocking conditions (like input exhaustion)
73     automatically. 
74
75     \section ppi_packets Packets
76
77     The PPI processes packets and uses the <a href="@TOPDIR@/Packets/doc/html/index.html">Packet
78     library</a> to handle them. All packets are passed around as generic \ref senf::Packet
79     references, the PPI does not enforce any packet type restrictions.
80
81     \section ppi_modules Modules
82
83     A module is represented by a class derived from senf::ppi::Module. Each module has several
84     components:
85
86     \li It may have any number of \ref ppi_connectors (inputs and outputs)
87     \li Each module declares flow information which details the route packets take within the
88         module. This information does not define how the information is processed, it only tells,
89         where data arriving on some input will be directed at (\ref
90         senf::ppi::module::Module::route())
91     \li The module might take additional parameters.
92     \li The module might also register additional \ref ppi_events.
93
94     Generally, modules are divided into several categories:
95
96     \li \ref io_modules receive external data or forward packets out of the PPI
97     \li \ref routing_modules forward packets within the network
98     \li \ref adapter_modules are used to connect incompatible connectors to each other
99     \li Application modules are modules implemented to perform an applications function
100
101     Of these modules, normally only the application modules need to be implemented since the library
102     provides an extensive set of reusable modules.
103     
104     The following example module declares three \ref ppi_connectors: \c payload, \c stuffing and
105     \coutput. These connectors are defined as \e public data members so they can be accessed from
106     the outside. This is important as we will see below.
107
108     \code
109       class RateStuffer
110           : public senf::ppi::module::Module
111       {
112           SENF_PPI_MODULE(RateStuffer);
113
114           senf::ppi::IntervalTimer timer_;
115
116       public:
117           senf::ppi::connector::ActiveInput payload;
118           senf::ppi::connector::ActiveInput stuffing;
119           senf::ppi::connector::ActiveOutput output;
120
121           RateStuffer(unsigned packetsPerSecond)
122               : timer_(1000u, packetsPerSecond)
123           {
124               route(payload, output);
125               route(stuffing, output);
126
127               registerEvent( timer_, &RateStuffer::tick );
128           }
129
130       private:
131           void tick()
132           {
133               if (payload)
134                   output(payload());
135               else
136                   output(stuffing());
137           }
138       };
139     \endcode
140
141     The constructor will declare flow information using senf::ppi::module::Module::route(). Then the
142     module registers an interval timer which will fire <tt>packetsPerSecond</tt> times every
143     <tt>1000</tt> milliseconds.
144
145     The module processing is very simple: Whenever a timer tick arrives a packet is sent. If the \c
146     payload input is ready (see \ref ppi_throttling), a payload packet is sent, otherwise a stuffing
147     packet is sent. The module will therefore provide a constant stream of packets at a fixed rate
148     on \c output (see the 
149     <a href="@TOPDIR@/Examples/RateStuffer/doc/html/index.html">RateStuffer</a> example application 
150     for a slightly different approach)
151     
152     An example module to generate the stuffing packets could be
153
154     \code
155       class CopyPacketGenerator
156           : public senf::ppi::module::Module
157       {
158           SENF_PPI_MODULE(CopyPacketGenerator);
159       public:
160           senf::ppi::connector::PassiveOutput output;
161
162           CopyPacketGenerator(Packet template)
163               : template_ (template)
164           {
165               noroute(output);
166               output.onRequest(&CopyPacketGenerator::makePacket);
167           }
168
169       private:
170           Packet template_;
171
172           void makePacket()
173           {
174               output(template_.clone());
175           }
176       };
177     \endcode
178
179     This module just produces a copy of a given packet whenever output is requested.
180
181     \see senf::ppi::module::Module
182
183     \section ppi_connectors Connectors
184     
185     The input and output attachment points of a module are called connectors. Each connector may be
186     active or passive. This gives us 4 types of connectors:
187
188     \li senf::ppi::connector::ActiveInput
189     \li senf::ppi::connector::ActiveOutput
190     \li senf::ppi::connector::PassiveInput
191     \li senf::ppi::connector::PassiveOutput
192
193     An \e active connector (input or output) is <em>activated by the module</em> to send data or to
194     poll for available packets. This means, the modules processing routine will call the connector
195     without being signaled by the framework to read the connector. It just actively fetches a
196     Packet.
197
198     A \e passive connector is <em>signaled by the framework</em> to fetch data from the module or to
199     pass data into the module. The module must register a callback which will be called, whenever a
200     packet is requested from the module or whenever a new packet is made available for the module to
201     process.
202
203     To send or receive a packet (either actively or passively) the module just calls the
204     connector. It is permissible to generate or process multiple packets in one iteration. However,
205     you must ensure yourself that enough packets are available to be read if more than one packet
206     shall be read. It is also permissible to not handle a packet at all even if signaled to do
207     so. The packet will automatically be queued.
208
209     To provide this flexibility, all input connectors incorporate a packet queue. This queue is
210     exposed to the module and allows the module to optionally process packets in batches.
211
212     \see \ref senf::ppi::connector
213
214     \section ppi_connections Connections
215
216     \image html ratestuffer.png Simple RateStuffer
217
218     To make use of the modules, they have to be instantiated and connections have to be created
219     between its connectors. It is possible to connect any pair of input/output connectors as long as
220     one of them is active and the other is passive.
221     
222     It is possible to connect two active or passive connectors with each other using a special
223     adaptor module (senf::ppi::module::PassiveQueue or senf::ppi::module::ActiveFeeder
224     respectively).
225
226     To complete our simplified example: Lets connet senf::ppi::module::ActiveSocketReader and
227     senf::ppi::module::PassiveSocketWriter to our example module:
228
229     \code
230       RateStuffer rateStuffer (10);
231
232       senf::Packet stuffingPacket = senf::DataPacket::create(...); 
233       CopyPacketGenerator generator (stuffingPacket);
234
235       senf::UDPv4ClientSocketHandle inputSocket (1111);
236       senf::ppi::module::ActiveSocketReader udpInput (inputSocket);
237
238       senf::UDPv4ClientSocketHandle outputSocket ("2.3.4.5:2222");
239       senf::ppi::module::PassiveSocketWriter udpOutput (outputSocket);
240
241       senf::ppi::module::PassiveQueue adaptor;
242
243       senf::ppi::connect(udpInput, adaptor);
244       senf::ppi::connect(adaptor, rateStuffer.payload);
245       adaptor.qdisc(ThresholdQueueing(10,5));
246       senf::ppi::connect(generator, rateStuffer.stuffing);
247       senf::ppi::connect(rateStuffer, udpOutput);
248
249       senf::ppi::run();
250     \endcode
251
252     This application will read udp-packets coming in on port 1111 and will forward
253     them to port 2222 on host 2.3.4.5 with a fixed rate of 10 packets / second.
254     
255     We start of by instantiating the necessary modules. Then the connections between these modules
256     are set up by successively connecting each output connector to an in put connector. As can be
257     seen, the name of the connector can be left of if it is named \c output or \c input
258     respectively.
259
260     The buffering on the udpInput <-> rateStuffer adaptor is changed so the queue will begin to
261     throttle only if more than 10 packets are in the queue. The connection will be unthrottled as
262     soon as there are no more than 5 packets left in the queue (see \ref ppi_throttling).
263
264     \section ppi_throttling Throttling
265
266     Throttling and throttle notifications at it's base is about handling blocking conditions. The
267     most straight forward blocking condition is that of a file descriptor not being available for
268     reading resp. writing. Other blocking conditions can arise for example when a queue fills up or
269     if a module for some application specific reason does not want to handle packets for a period of
270     time.
271
272     All this is handled using throttle notifications. We need throttle notifications so a passive
273     connector can tell it's connected peer that it cannot service further requests until an
274     unthrottle notification is sent. This tells us, that from the view of someone implementing a
275     module, throttle notifications will always be received on active connectors and be sent on
276     passive connectors.
277
278     This tells us, that the direction of control flow (the throttle notifications) is from passive
279     to active connectors and does \e not depend on the direction of data flow (which flows from
280     output to input connector). Thinking about this, this makes sense: The module with the active
281     connector is the one initiating the data processing (after all, it is the \e active part) and
282     needs to be told not to request or send packets on it's connector since the connected passive
283     peer cannot handle the request.
284
285     So if a passive connector cannot handle requests, the connector must be \e throttled. Throttling
286     the connector will forward a throttle notification to its peer. The peer then handles the
287     throttling notification.
288
289     There are two ways, throttle notifications can be handled: By automatic throttling or by
290     registering callbacks. The default is <em>automatic throttling</em>.
291
292     <em>Automatic throttling</em> is based on the routing information available to the module. Every
293     notification received is forwarded within the module along all known routes from active to
294     passive connectors (routes which connect to active or passive connectors are absolutely valid,
295     they just are not \e forwarding routes, they are ignored by the throttle
296     notifications). Together with automatic event throttling (see \ref ppi_events), this is all that
297     is normally needed to handle throttle notifications: By forwarding the notifications we ensure,
298     that a module's passive connectors will only be signaled when it's corresponding active
299     connectors are not throttled (as defined by the routing information). The module is therefore
300     not called until the connector(s) are untrhottled.
301
302     <em>Throttle callbacks</em> can optionaly be registerd (with automatic throttling enabled or
303     disabled, see \ref senf::ppi::connector::ActiveConnector) to be called when a throttle
304     notification is received. The callback may then handle the notification however it sees fit, for
305     example by manually throttling some passive connector (see \ref
306     senf::ppi::connector::PassiveConnector). 
307
308     To enable/disable automatic throttling, the \ref senf::ppi::Module::route() command returns a
309     reference to a \ref senf::ppi::Route instance. If this route is \e forwarding route, (that is,
310     of the connectors is passive and the other is active), the return value will be derived from
311     \ref senf::ppi::ForwardingRoute which provides members to control the throttle notification
312     forwarding.
313     
314     \see 
315         senf::ppi::module::Module \n
316         senf::ppi::Route
317
318     \section ppi_events Events
319
320     Modules may register additional events. These external events are very important since they
321     drive the PPI framework. Events are like external calls into the module network which are sent
322     whenever some event happens. Some possible events are
323     \li timer events (senf::ppi::IntervalTimer)
324     \li read or write events on some file descriptor (senf::ppi::IOEvent)
325     \li internal events (senf::ppi::IdleEvent)
326
327     The PPI really is not concerned, how the events are called and what information is needed to
328     perform the call. This is handled by the <a
329     href="@TOPDIR@/Scheduler/doc/html/index.html">Scheduler</a>, which is wrapped by the event
330     classes.
331     
332     All events are derived from senf::ppi::EventDescriptor. The base class allows to enable and
333     disable the event. Each type of event will take descriptor specific constructor arguments to
334     describe the event to be generated. Events are declared as (private) data members of the
335     module and are then registered using senf::ppi::module::Module::registerEvent(). 
336
337     Each event when signaled is described by an instance of the descriptor specific \e
338     descriptorType \c ::Event class. This instance will hold the event specific information (like
339     scheduled time of the event, file handle state and so on). This information is passed to the
340     callback.
341
342     Additionaly, events are valid routing targets. This feature allows events to be disabled and
343     enabled by throtling notifications. For the sake of routing, an event may be used like an active
344     input or output. Iit is \e active from the PPI's point of view since it is signaled from the
345     outside and not by some module. It may be either input or output depending on the operation the
346     event controls.
347
348     If we take into account event routing, we can extend the \c RateStuffer constructor accordingly:
349
350     \code
351           RateStuffer(unsigned packetsPerSecond)
352               : timer_(1000u, packetsPerSecond)
353           {
354               route(payload, output);
355               route(stuffing, output);
356               route(timer_, output);   // (*)
357
358               registerEvent( timer_, &RateStuffer::tick );
359           }
360     \endcode
361
362     We have added the marked route call. This way, the \c timer_ will receive throttling
363     notifications from the output: Whenever the output is throttled, the event will be disabled
364     until the output is unthrottled again.
365
366     \see senf::ppi::EventDescriptor
367
368     \section ppi_flows Information Flow
369
370     The above description conceptually introduces three different flow levels:
371      
372     \li The <em>data flow</em> is, where the packets are flowing. This flow always goes from output
373         to input connector.
374     \li The <em>execution flow</em> describes the flow of execution from one module to another. This
375         flow always proceeds from active to passive connector.
376     \li The <em>control flow</em> is the flow of throttling notifications. This flow always proceeds
377         \e opposite to the execution flow, from passive to active connector.
378
379     This is the outside view, from without any module. These flows are set up using
380     senf::ppi::connect() statements.
381
382     Within a module, the different flow levels are defined differently depending on the type of
383     flow:
384     
385     \li The <em>data flow</em> is defined by how data is processed. The different event and
386         connector callbacks will pass packets around and thereby define the data flow
387     \li Likewise, the <em>execution flow</em> is defined parallel to the data flow (however possible
388         in opposite direction) by how the handler of one connector calls other connectors.
389     \li The <em>control flow</em> is set up using senf::ppi::Module::route statements (as long as
390         automatic throttling is used. Manual throttling defines the control flow within the
391         respective callbacks).
392
393     In nearly all cases, these flows will be parallel. Therefore it makes sense to define the \c
394     route statement as defining the 'conceptual data flow' since this is also how control messages
395     should flow (sans the direction, which is defined by the connectors active/passive property).
396
397     \see \ref ppi_implementation
398  */
399
400 /** \page ppi_implementation Implementation Notes
401     
402     \section processing Data Processing
403
404     The processing in the PPI is driven by events. Without events <em>nothing will happen</em>. When
405     an event is generated, the called module will probably call one of it's active connectors.
406
407     Calling an active connector will directly call the handler registered at the connected passive
408     connector. This way the call and data are handed across the connections until an I/O module will
409     finally handle the request (by not calling any other connectors).
410
411     Throttling is handled in the same way: Throttling a passive connector will call a corresponding
412     (internal) method of the connected active connector. This method will call registered handlers
413     and will analyze the routing information of the module for other (passive) connectors to call
414     and throttle. This will again create a call chain which terminates at the I/O modules. An event
415     which is called to be throttled will disable the event temporarily. Unthrottling works in the
416     same way.
417
418     This simple structure is complicated by the existence of the input queues. This affects both
419     data forwarding and throttling:
420     \li A data request will only be forwarded, if no data is available in the queue
421     \li The connection will only be throttled when the queue is empty
422     \li Handlers of passive input connectors must be called repeatedly until either the queue is
423         empty or the handler does not take any packets from the queue
424
425
426     \section ppi_logistics Managing the Data Structures
427
428     The PPI itself is a singleton. This simplifies many of the interfaces (We do not need to pass
429     the PPI instance). Should it be necessary to have several PPI systems working in parallel
430     (either by registering all events with the same event handler or by utilizing multiple threads),
431     we can still extend the API by adding an optional PPI instance argument.
432
433     Every module manages a collection of all it's connectors and every connector has a reference to
434     it's containing module. In addition, every connector maintains a collection of all it's routing
435     targets. 
436
437     All this data is initialized via the routing statements. This is, why \e every connector must
438     appear in at least one routing statement: These statements will as a side effect initialize the
439     connector with it's containing module.
440
441     Since all access to the PPI via the module is via it's base class, unbound member function
442     pointers can be provided as handler arguments: They will automatically be bound to the current
443     instance. This simplifies the PPI usage considerably. The same is true for the connectors: Since
444     they know the containing module, they can explicitly bind unbound member function pointers to
445     the instance.
446     
447     \section ppi_random_notes Random implementation notes
448     
449     Generation of throttle notifications: Backward throttling notifications are automatically
450     generated (if this is not disabled) whenever the input queue is non-empty \e after the event
451     handler has finished processing. Forward throttling notifications are not generated
452     automatically within the connector. However, the Passive-Passive adaptor will generate
453     Forward-throttling notifications whenever the input queue is empty.
454
455     \section ppi_classdiagram Class Diagram
456
457     \image html classes.png
458  */
459
460 \f
461 // Local Variables:
462 // mode: c++
463 // fill-column: 100
464 // c-file-style: "senf"
465 // indent-tabs-mode: nil
466 // ispell-local-dictionary: "american"
467 // mode: flyspell
468 // mode: auto-fill
469 // End:
470