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