4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 // Stefan Bund <g0dil@berlios.de>
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.
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.
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.
23 /** \mainpage Example introducing the Packet Processing Infrastructure
25 This example application implements a simple PPI application: It will read UDP packets from an
26 input port and will forward them to another port at a fixed packet rate. If the input stream
27 does not provide enough packets, empty UDP packets will be sent instead.
29 \section run Running the example
31 Running the example is a little bit more complicated since we need to provide example UDP
32 packets so we can see the application at work. We do this using \c netcat. We open several shell
33 windows and run the following commands, each in it's own window
35 The first command listens for incoming UDP packets on port 44345:
40 The next command starts the \c ratestuffer
42 # cd .../Examples/RateStuffer
47 We should now see '<idle>' messages arriving in the first window once per second. We now can
48 start another \c netcat to send packets to the input port.
51 # nc -u localhost 44344
52 < type any text here >
55 Whenever we send out a packet with CR in the last window we should see it appear in the first
56 one. If we send out packets faster than 1 packet per second, they will start to be discarded if
57 more than two packets are in flight.
59 \image html screenshot.png
61 \section setup Module setup
63 <div class="diamap" name="ratestuffer">
64 <span coords="101,139,220,206">\ref senf::ppi::module::ThrottleBarrier</span>
65 <span coords="241,152,365,219">\ref senf::ppi::module::PassiveQueue</span>
66 <span coords="606,346,748,400">\ref senf::ppi::module::PassiveSocketSink<></span>
67 <span coords="528,190,647,257">\ref RateFilter</span>
68 <span coords="387,165,511,245">\ref senf::ppi::module::PriorityJoin</span>
69 <span coords="0,0,149,53">\ref senf::ppi::module::ActiveSocketSource<></span>
70 <span coords="241,235,365,289">\ref senf::ppi::module::CloneSource</span>
72 \htmlonly <img src="ratestuffer.png" border="0" alt="ratestuffer" usemap="#ratestuffer"> \endhtmlonly
74 Above image depicts the module setup implementing the rate stuffer. A
75 senf::ppi::module::ActiveSocketSource reads the incoming UDP packets and sends them into a
76 senf::ppi::module::PassiveQueue (via a senf::ppi::module::ThrottleBarrier).
78 The \a queue feeds the packets into a senf::ppi::module::PriorityJoin. The CloneSource
79 \a generator is fed as second input into the \a join to provide the stuffing packets.
81 The RateFilter \a rateFilter reads packets from it's input at a fixed rate and writes them into
82 the senf::ppi::module::PassiveSocketSink \a udpSink. The senf::ppi::module::PriorityJoin
83 ensures that read requests of the RateStuffer's input are always serviced, either from the \a
84 queue or, if the \a queue output is throttled, from the \a generator.
86 The \a barrier is not strictly necessary. However, it makes the behavior of the RateStuffer
87 predictable in the case where packets need to be dropped. Without the
88 senf::ppi::module::ThrottleBarrier, the packets will be left in the kernel socket queue. Packets
89 will only start to be dropped when that queue fills up. The size of this queue cannot be easily
90 manipulated and it's initial size is immense. So to stop the kernel queue from filling up with
91 increasingly out-of-date packets, we add the \a barrier which will explicitly read and drop
94 \section code Example code
96 \dontinclude ratestuffer.cc
98 The code starts out including the necessary header files
104 We also define some namespace aliases
109 The RateStuffer application is based on one additional application module.
111 \subsection ratefilter The RateFilter module
113 The RateFilter module simply forwards packets at a fixed rate.
118 Both connectors of the RateFilter module are active. The module is driven by a
119 senf::ppi::IntervalTimer.
123 The event is initialized to fire every \a interval nanoseconds. The traffic is routed 'across'
124 the timer which controls the traffic. This routing lets the module automatically handle
125 throttling events. The timer is registered to call RateFilter::timeout().
129 The event handler is quite simple: Every \a interval nanoseconds a packet is read from \a input
130 and forwarded to \a output.
132 This is all there is to the RateFilter module. Due to the routing setup, the timer will
133 automatically be disabled should either \a input or \a output become throttled. However, in this
134 specific case this should never happen: The \a input is connected (via the \a join) to the
135 senf::ppi::module::CloneSource, which will never throttle. The \a output is connected to a UDP
136 socket which also never throttles.
138 \subsection ratestuffer The RateStuffer subnet
140 We decide to implement the RateStuffer as a subnet or collection. This is a simple struct or
141 class which contains all the modules necessary for a specific functionality. The modules are
142 initialized and connected in the class's constructor. External connectors are exported as
143 references to the corresponding module connectors:
148 First the needed modules are declared. We have
149 - the \a barrier to discard incoming packets sent to fast
150 - the \a queue to receive incoming packets and create throttling notifications
151 - the \a generator to create the stuffing packets
152 - the \a join to combine the input stream from the \a queue with the stuffing packet stream
153 - the \a rateFilter to generate the fixed rate output stream
157 Here we declare the external connectors. The subnetwork exports a single input and output
158 connector. The external connectors are declared as \e references.
162 The constructor now initializes all the local objects. We pass the template \a packet to the \a
163 generator and set the timing \a interval of the \a rateFilter.
165 The \a input and \a output connector references are bound to the corresponding connectors we
166 want to expose: \a input to the \a barrier's \a input and \a output to the \a rateFilter's \a
171 The constructor body sets up the connections within the subnetwork. Finally, we set the queueing
172 discipline of the \a queue. This Completes the RateStuffer. This subnetwork can now be used like
175 \subsection main Application setup
177 The applications main() method starts out by initializing the socket handles
182 The \a inputSocket is listening on port 44344 while the \a outputSocket will send packets to
183 port 44345 on localhost. The \a outputSocket uses the senf::ConnectedUDPv4SocketProtocol which
184 is compatible with the senf::ppi::module::PassiveSocketSink module.
188 Here we allocate the components:
190 - \a udpSource to read the packets from \a inputSocket
191 - \a stuffer for the real work and
192 - \a udpSink to send the packets to \a outputSocket
196 The \ref senf::ppi::connect() calls setup the necessary connections.
198 The module setup is complete, \ref senf::ppi::run() is called to enter the event loop.
207 // comment-column: 40
208 // c-file-style: "senf"
209 // indent-tabs-mode: nil
210 // ispell-local-dictionary: "american"
211 // compile-command: "scons -u doc"