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