<?xml version="1.0"  encoding="ISO-8859-2"?> 
<!DOCTYPE zprava SYSTEM "techrep.dtd"> 
<zprava cislo="32/2005" jazyk="en"> 
<nazev>Hardware-Accelerated NetFlow Probe</nazev> 
<autor>Martin Žádník and Ladislav Lhotka</autor>
<datum>14. 12. 2005</datum> 

<h1>Abstract</h1>

<p> With ever-growing volume of data being transferred over the Internet, the need for
   reliable monitoring becomes more urgent. Monitoring devices should be able to provide accurate information
   such as traffic patterns,
   statistics and various anomalies. This technical report describes an
   implementation of a network flow monitoring system using a dedicated hardware
   platform cooperating with the host PC.  By exploiting the
   hardware-software codesign principle, 
   we implemented time-critical functions in hardware and the rest in
   software. This way, the NetFlow probe offers good performance at low
   cost.  After explaining the basics of flow measurement techniques
   we describe the design of the probe and function of the individual units.
   Finally, results and future work are also discussed.
</p>


<h1>Introduction</h1>

<p> Most modern communication services (world wide web, streaming, databases, e-mail,
   on-line shops etc.) now use the Internet infrastructure. Its reliable operation
   also depends on large-scale
   monitoring capable of providing accurate data about
   traffic patterns, applications used, hostile activities etc. Such monitoring systems can help
   network operators to manage their current networks or plan new network
   topologies. Other management techniques such as bandwidth provisioning, detecting DoS attacks,
   billing and accounting also require detailed monitoring. Currently available
   monitoring devices have their limitations in terms of performance
   and flexibility. In particular, for security-related applications
   it is not acceptable to get information about only a random portion of the
   network traffic when the monitoring device becomes overloaded, for
   example during a DoS attack.
</p>

<p> NetFlow as a general method for flow monitoring <cite href="RFC3954"/>, first implemented in Cisco routers, is
   the most widely used measurement solution today. Statistics on
   IP traffic
   flows provide information about who communicates with whom, how
   long, how often, using what
   protocol and service and also how much data was transfered.
</p>
<p>So far, Netflow data are usually acquired and exported by IP
routers. Such a setup has several drawbacks, namely
<ul>
  <li>Routers are by definition visible Layer 3 systems that can
  easily be discovered by simple tools such as
  <prikaz>traceroute</prikaz>. Consequently, they can become targets
  for all types of attacks.</li>
  <li>The main task of routers is to forward datagrams and exchange
  routing information with their neighbours. The processing power
  available is thus rather limited and so operations on Netflow data
  do not usually go much beyond simple export of raw flow records.</li>
  <li>As a special case of the previous item, some routers impose
  sampling on the incoming traffic. Even if sampling is not strictly
  required, in some cases it is the only way for keeping the router
  operational, especially when high-speed interfaces are monitored.</li>
</ul>
In contrast, our standalone monitoring probe is essentially a stealth
device -- invisible at both Layer 3 and 2 -- dedicating all its
resources to the tasks of flow record acquisition and processing. 
</p>


<h2>Flow</h2>

<p> A IP traffic flow is a set of packets with common properties that
    passes an observation point.  Those common properties can be any
    information contained in packet headers or related to the packet <cite
    href="RFC3917"/>.
</p>

<h2>Flow characteristics</h2>

<p> From the definition of IP flow it is clear that we can always obtain
   different flows by applying different views on the same set of packets.
   For example, aggregation according to addresses, ports and sequence numbers
   results in one packet per flow.  On the other hand, when using IP
   version as the only distinguishing property, we get just
   two flows, one for IPv4 and another for IPv6. The selected
   properties thus influence the size and duration of flows.
</p>
<p>For some transport protocols, the end of a flow can be determined
   from specific events such as the presence of the FIN flag in the
   TCP header <cite
     href="RFC3917"/>. For protocols that do not provide such an indication,
   two timeouts are used for terminating the flows. 
   The <i>inactive timeout</i> controls how long the flow is kept in
   memory when no incoming packets belonging to the flow are seen.
   On the other hand, the <i>active timeout</i> defines the time
   period with which long-lasting flows are artificially terminated
   and information about them exported.
</p>

<h2>Sampling</h2>

<p> Nowadays, the Internet traffic has no lack of malicious traffic
such as DoS attacks, smurfs and port scans. Such traffic often
geenrates a large number of flows. Consequently, NetFlow monitoring
systems may become overwhelmed and thus unable to give vital
information about those attacks.  Many techniques were published aimed
at protecting the monitoring elements so that they continue operation
even when faced with massive vloumes of malicious traffic. Examples
are:
</p>

<p>
<dl>
   <dt>Input sampling</dt>

   <dd>Input sampling of incoming packets is the easiest way how to decrease
      the traffic volume to be processed, and also decrease the number of new flows
      during attacks where every incoming packet belongs to a new flow. On the
      other hand, sampling makes it difficult to estimate precise
      flow statistics. 
   </dd>

   <dt>Output Sampling</dt>

   <dd>Rate of exported flow records is strongly dependent on the
   actual traffic mix.  Output sampling can keep it in a specified range
   and prevent collector from being overwhelmed by aggressive export
   rate during traffic peaks or attacks.
   </dd>

   <dt>Sample and Hold</dt>

   <dd>This method is quite similar to input sampling but with the following
      twist. As with ordinary sampling, each packet is sampled with certain
      probability. However, for every new entry in the flow memory, all subsequent
      packets belonging to that flow are protected from sampling
      the flow memory, a new item is created. This way we obtain
      precise data about large flows <cite href="Es03"/>.
   </dd>

   <dt>Adaptive Input Sampling</dt>

   <dd>A static sampling rate is either suboptimal at low traffic volumes or
      can exhaust resources (memory, bandwidth) or cause other difficulties at
      high traffic volumes.  Adaptive Input Sampling keeps the device load
      within reasonable limits while using the optimal
      sampling rate for all traffic mixes. 
   </dd>

   <dt>Matching</dt>

   <dd>
      Only those packets that meet certain rules are sampled.
   </dd>
</dl>
</p>


<h1>Block structure of the Netflow probe</h1>

<p> The Netflow probe consists of two parts: hardware and software.
   The hardware part processes incoming packets at high
   speed while the software together with an ordinary network card
   handle the task of transmitting
   flow records to a remote collector. This division of functions
   <a href="#fig1">Figure 1</a>) guarantees very good performance and
   flexibility in processing methods and export formats.
</p>

<!--<obr>obrazek pocitace a karty</obr>-->
<p>
<obr id="fig1" src="partitioning" >Partitioning of system</obr>
</p>

<p>
   <!-- Dopsat neco o PC --> 
</p>


<h1>Hardware/firmware characteristics</h1>


<p> As a hardware platform platform we use the COMBO cards developed
by the Liberouter project <cite href="CoHW"/>.
   COMBO6 is a universal PCI card, which can be used in
   various applications. It consists of Xilinx Virtex-II XC2V3000 FPGA, 2MB
   Ternary CAM, 256MB DRAM and three SSRAM chips, each with 2MB of memory. 
   Various add-on cards can be used with the COMBO6 card, for example the
   COMBO-MTX or COMBO-SFP interface cards.  Additional cards are now
   being developed with
   more on-board memory and a variety of network interfaces (GE, 10GE,
   PoS STM-16). With necessary modifications, the flow data
   acquisition firmware will be able to use the new interface cards as
   well.
</p>

<p>During one year we have developed a fully functional prototype.  The
   firmware is somewhat limited by the interface types and resources
   available on the current COMBO cards: only Gigabit Ethernet
   interfaces are supported and the maximum number of flows that can be
   monitored simultaneously is 65536.
</p>

<!--<obr>obrazek zapojeni v siti</obr>-->
<p><obr id="fig2" src="repeater" >NetFlow probe as repeater</obr></p>


<p> The probe works as a T-splitter (see <a href="#fig2">Figure 2</a> ): when inserted into a network
   link, the traffic is passed directly to the original destination and a
   separate copy of link data is processed by the probe in parallel. From the
   network perspective, the probe can be classified as a repeater that is
   invisible at both the network and link layer.  
</p>

<p> The copy of link data is processed using an FPGA (Field Programmable
   Gate Array). FPGAs allow us to create our own application-specific
   architecture. The block diagram of the NetFlow firmware architecture is in  
   <a href="#fig3">Figure 3</a>.  Characteristics important from the network operator
   viewpoint are discussed in the following paragraphs. We describe
   only those units that are crucial for understanding the operation
   of the probe.
</p>
<p>
<obr id="fig3" src="block_struct" >Block structure of firmware architecture</obr>
</p>

<p> The firmware is able to process IPv4 and IPv6 datagrams of all
sizes in full 1 Gbps line rate. CRC checksum is verified and a 32-bit
timestamp with the precision of 640ns assigned.  In the Input Buffer
(IBUF), numbers of bad and dropped packets as well as overall
statistics of the incoming traffic packets are recorded. We plan to
implement both static and adaptive input sampling in the near future.
</p>

<p><obr id="fig4" src="hfe" >HFE throughput</obr></p>

<p>In the Header Field Extractor unit (HFE), headers of incoming
packets are parsed and a configurable set of "interesting" header
fields, flags and other characteristics are extracted. These are
typically source and destination IP addresses, source and destination
ports, protocol number, actual packet length, TCP flags, DSCP code
point, ICMP options and so on. At present, this unit is the bottleneck
of the processing pipeline (see <a href="#fig4">Figure 4</a>) and we are
thus working on a new HFE implementation with considerably improved
performance.
</p>

<p> We use hash values as unique identifiers of flow
records. By default, five header fields are used as inputs for the
hash function CRC-64 implemented by the HGEN unit: two IP addresses,
two IP ports and the protocol number. If necessary, selected bytes of
these five key fields can be masked out in order to get more
aggregated flows. We use the first 57 bits from the 64-bit hash value
as the flow identifier.
</p>

<p> For indexing and scanning the flow cache we use an index vector of
2^M pointers to lists that are able to store up to eight flow records each
(see <a href="#fig6">Figure 6</a>).  We use M bits of previously
computed hash value for finding the appropriate list. The rest of the hash value is stored in the flow
record for fast comparison against new flows.  The CRC-64 hash
function distributes the flow records uniformly among the available
2^M positions. Applying the standard M/M/N queuing theory, we can express
the probability that the some list becomes full as <cite
href="Mo05"/>:
</p> 

<p>
  <obr  id="fig5" src="equation">Probability of list
  overflow</obr>

</p>

<p>
where  N is the length of the list, X maximum capacity of
the flow cache and g = 2<sup>M</sup> / X.
</p>

<p>
   In our case we have N = 8 and g = 2<sup>15</sup> / 2<sup>16</sup>. 
   So P(list_full) = 8.5948x10<sup>-4</sup>.
</p>

<p>
   It is up to the operator to decide what to do when the list becomes
   full. He can instruct the device to drop the incoming packet that
   would not fit to the list or to export some record(s) from the list
   and replace it with a new record about the incoming packet. We
   plan to increase the size of the flow memory and thus decrease the
   probability of list overflow.
</p>

<p>
The use of hashing implies that different
flows may occasionally map to the same key. However, the
probability of such an undetectable collision is very small -- its
upper bound is
</p>

<p>
   <blockquote>
         P(collision) = X / 2<sup>L</sup>,
   </blockquote>
</p>

<p>
where X is maximal number of flows in the memory and L the length of
the hash value.  This gives for X=2<sup>16</sup> and L=57 the value
P(collision) = 4.54x10<sup>-13</sup>. This means a collision appears
less than once a week on the average. The hash function is randomly
initiated every time the device is started so that the hash values
cannot be predicted. We also plan to add provisions for detecting flow
collisions based on checking the original key field. 
</p>
<p>
<obr  id="fig6" src="index_table">Memory format</obr>
</p>
<p>The states of flow records are kept in a bidirectional
   list. The list is sorted by timestamps. We can set very precise
   timeouts: the inactive timeout in the range 0-60s with a
   precision of 10 microseconds and the
   active timeout in the range 0-1200s with a precision of
   1 microsecond.
</p>

<p>Traffic sampling is always optional. Apart from the standard static input
   sampling we also implemented the sample-and-hold technique.  Two
   sampling methods are implemented:
   <ul>
     <li>regular sampling (the default method)  means that every
   N-th packet is taken, and</li>
     <li>random sampling takes every incoming packet with probability 1/N.</li>
   </ul></p>
<p>The sampling
   rate parameter N ranges between 1 (every packet is taken) and
   65536, which means that one in 64536 packets is taken on the average.</p>
<p>More sophisticated adaptive
   sampling techniques are also being investigated.  
</p>

<h1>Block units</h1>
<p>
   Incoming packets from network interface are entering the <i>Input
      Buffer</i> (IBUF)
block. For each packet the CRC is checked and only those with a
correct CRC pass through. Every packet is assigned a timestamp and saved in the
internal IBUF memory that serves as short-time storage for incoming
packets.
   
</p>
<p>
   Packets with assigned timestamp are then processed by the <i>Header
   Field Extractor</i> (HFE). It is a virtual RISC-like processor
   implemented in the FPGA controlled by a specific instruction set
   that is specially tailored for parsing packet headers. It reads
   packet from <i>Input Buffer</i>, analyzes control information in
   its headers, extracts required fields from IP and transport headers
   and assembles a unique key that identifies each flow.  The key
   consists of IP source address, IP destination address, source port,
   destination port, transport layer protocol and type of service (ToS).
   After processing each datagram HFE writes the extracted information
   to the <i>Unified Header FIFO</i> (UH_FIFO).
</p>
<p>
   Unified Headers from UH_FIFO are processed by <i>UH driver</i> (UHDRV). 
   UHDRV works as follows.
   <ol>
      <li>Check the control register (<i>HFE_REG</i>) of the Unified Header.</li>
      <li>Choose one of sixteen masks according to HFE_REG.</li>
      <li>Process the header using the chosen mask</li>
      <li>Send results to <i>Statistical FIFO</i> and to <i>Hash Generator</i></li>
   </ol> 
</p>
<p>
   The layout of HFE_REG is<cite href="Ha05"/>:
   <blockquote>
      <pre>

  1                   1   0                                     0
  5   4   3   2   1   0   9   8   7   6   5   4   3    2   1   0
+---+---+---+---+---+---+---+---+---+---+---+---+---+----+---+---+
|  Reserved |TCP|MPL|MP |802|Oth|Bad|DST|SRC|IP |IP |RUNT|Len|CRC|
|           |flg|S m|LSu|.1Q|err|Eth|val|val|ver|   |    |   |   |
+---+---+---+---+---+---+---+---+---+---+---+---+---+----+---+---+

 0	CRC 0 - good, 1 - bad
 1	length 0 - OK, 1 - longer then MTU
 2	RUNT 0 - OK, 1 - shorter then 64 bytes
 3	IP 0 - IP, 1 - NonIP
 4	IPver 0 - IPv4, 1 - IPv6
 5	SRC_PORT validity 1 - SRC_PORT valid, 0 - SRC_PORT dosen't contain
	valid data
 6	DST_PORT validity 1 - DST_PORT valid, 0 - DST_PORT dosen't contain
	valid data
 7	BAD_ETH 0 - frame seems ok, 1 - ethernet frame is bad (VLAN, ...)
 8	OTHER_ERR: 0 - good, 1 - other unspecified error
 9	802.1Q tag present
10	MPLS unicast
11	MPLS multicast
12	TCP flags are valid
13-15	reserved
      </pre>
   </blockquote>
</p>

<p>
   <i>Hash Generator</i> (HGEN) takes the key fields and feeds them to
   the CRC-64 function. The resulting hash value serves as the flow
   identifier. HGEN allows to process 32 bits of input in one tact at
   100MHz, so the throughput is 3.2Gbps.
</p>
<p>
   The <i>Hash Search</i> (HSRCH) unit searches the flow cache for the
   entry that matches the generated hash value. This
operation can end up with several different results: 
<ul>
   <li>No matching entry is found so a new one is created.</li>
   <li>No matching entry is found but the flow cache is full.</li>
   <li>A matching entry is found.</li>
</ul>
   
The search result and additional data are transferred to the
<i>Manager</i>. It is also necessary to remove expired entries
according to requests from Manager and acknowledge it back.
</p>
<p>
   The <i>Manager</i> is responsible for keeping states of active and
   inactive flows.  For this purpose bidirectional linked list is
   used. New or updated flows are inserted at the top of the list so
   that the oldest ones gradually sink to the bottom.  It is then easy
   to identify inactive flows and send delete request to HSRCH.
   Another task of the Manager unit is to copy information coming from
   <i>Hash Search</i> to the
   Storage unit and vice versa. Since Storage can also generate delete
   requests, <i>Manager</i> must be careful to avoid duplicate
   requests to <i> Hash Search</i>.
</p>
<p>
   Statistical data is hold in <i>Storage</i> memory. The unit reads
   data from <i>Statistical FIFO</i> and performs different operations
   according to commands obtained from <i>Manager</i>.  The unit is
   responsible for checking whether records are not held for too long
   (starting timestamp of the flow is compared to the actual timestamp
   while flow statistics are updated). If it is the case, a delete request is
   sent to <i>Manager</i>.
</p>
<p>
Released records are stored in a circular buffer. This buffer is able
to generate interrupt request via PCI. The IRQ signal is raised if
either the number of records in exceeds a certain thresholds or a
timeout expires.
</p>
<p>
   Structure of the flow record is as follows:
</p>
<p>
   <blockquote>
      <pre>
63                                                                      0
+--------+--------+--------+--------+--------+--------+--------+--------+
|          START TIMESTAMP          |           PACKET COUNT            |
+--------+--------+--------+--------+--------+--------+--------+--------+
|     HFE_REG     |  TOS   |               BYTE COUNT                   |
+--------+--------+--------+--------+--------+--------+--------+--------+
|            END TIMESTAMP          |           RESERVED                |
+--------+--------+--------+--------+--------+--------+--------+--------+
|  FLAGS | PROTO  |TCP FLAG| RESERV |     SRC PORT    |      DST PORT   |
+--------+--------+--------+--------+--------+--------+--------+--------+
|            SRC IP 0               |             SRC IP 1              |
+--------+--------+--------+--------+--------+--------+--------+--------+
|            SRC IP 2               |             SRC IP 3              |
+--------+--------+--------+--------+--------+--------+--------+--------+
|            DST IP 0               |             DST IP 1              |
+--------+--------+--------+--------+--------+--------+--------+--------+
|            DST IP 2               |             DST IP 3              |
+--------+--------+--------+--------+--------+--------+--------+--------+

Meaning:
FLAGS   - Current sampling rate (one in FLAGS)
SRC IPv4 = SRC IP 0
DST IPv4 = DST IP 0
SRC IPv6 = SRC IP 0 * SRC IP 1 * SRC IP 2 * SRC IP 3
DST IPv6 = DST IP 0 * DST IP 1 * DST IP 2 * DST IP 3
							
      </pre>
   </blockquote>
</p>
   
<h1>Evaluating the Architecture</h1>
<p>
The  monitoring infrastructure has to be very accurate, reliable and
powerful. We created two different models. 
First we tried to estimate 
the throughput of the
design by experimenting with its abstract model. The experiment is
described in section Througput.

Probabilities of different collisions were discussed in the
previous section. But we have also implemented a special model and
performed simulations in order to verify the theory. 

</p>
<h2>Throughput</h2>
<p>
   We used the M/D/1 Kendall mass service system to define an
   analytic model of packet processing in the critical parts of the
   design. We were interested in the throughput of the design with
   different traffic mixes. The length of each queue was monitored to
   find out whether the corresponding unit is able to process all
   requests. A simplified view of the model based on Petri
   Net is shown in <a href="#fig7">Figure 7</a>.
</p>

<p>
 <obr  id="fig7" src="netflow_petri">Petri Net model of the flow
 processing firmware.</obr>  
</p>
<p>
   Our model was implemented in C++ using the SIMLIB simulation library.
</p>

<p><i>Experimental setup:</i></p>
<p>
With memory tables filled to 50 percent of their capacity we tried to
simulate an attack by flooding the probe with a large number
single-packet flows during one second.
</p>
<p><i>Results:</i></p>
<p>
After several simulation cycles
for different inter-packet intervals we
   have obtained the graph in <a href="#fig8">Figure 8</a>. Simulation results
   show that our probe should be capable to process 3 to 4 million packets
   per second, which is equivalent to 260ns interval between packets. 
</p>
<p>
   <obr  id="fig8" src="graph2">Maximal length of queues during
      simulation</obr>
   </p>

   <h2>Collisions</h2>
   <p>
      We randomly generated <i>Unified Headers</i> and processed them with
      the same CRC-64 function as implemented in the firmware. The
      <i>Hash Search</i> memory lookup procedure was simulated to find out
      the maximum length of index lists. The results are in <a
      href="#fig10">Figure 10</a>. Also the number of collisions caused by CRC
      reduction was counted.
   </p>
   <p><i>Experimental setup:</i></p>
   <p>
      We generated randomly packet headers with uniform distribution.
      Packets arrivals were simulated as a Poisson process and
      exponentially distributed lifetime of
      flows in the memory was used.
   </p>
   <p>
     The model started with empty flow memory and each simulation
     consisted of more than fifty
      thousand flows. 
      Number of flows in the memory during the simulation is shown in <a
         href="#fig9">Figure 9</a>.
      Model time was sixty minutes and it took 15 hours with 
      Pentium 4 running at 2 GHz to finish the simulation.   
      <obr  id="fig9" src="flowcount">Number of flows during simulation</obr> 
   </p>

   <p><i>Results:</i></p>
   <p>
      First, we were interested in the number of collisions caused by
      the method chosen for indexing the 2^15 lists of 8 flow entries.
      Collision in this case means that any of the lists becomes full
      (contains more than eight items).  <a href="#fig10">Figure 10</a>
      shows the distribution of lists lengths in the course of the simulation.
   </p>

   <p><obr id="fig10" src="lists" >Number
      of lists dependent on the occupation and time</obr></p>

   <p>
     Next, during this experiment we did not observe any single collision
     due to CRC space reduction.
   </p>

<h1>Conclusions</h1>
<p>
A functional prototype of the probe was tested on the access link
connecting the Brno Academic Computer Network to the CESNET2
backbone. The results so far are very promising.
</p>
<p>The probe firmware now works at 50MHz, which results in the
theoretical maximum throughput of 800 Mbit/s. With the new COMBO6X
card we will be able to double the clock rate and together with the
improved implementation of the <i>Header Field Extractor</i> this should
be more than enough for wire speed processing of Gigabit Ethernet links.
The flow cache currently has room for 64 thousand flows but this capacity will
soon be increased to 512 thousand flows. 
</p>

<p>The software part of the probe is described in another technical
report <cite href="Ce05"/>.</p>

<p>
   We will port the flow pocessing firmware to the new more powerful
   cards such as the COMBO6E/COMBO6X motherboards and COMBO-2XFPRO and
   COMBO-4SFPRO interface cards. That will allow us to monitor 10GE
   and PoS STM-16 links, although input sampling will be necessary for
   traffic rates exceeding 1.6 Gb/s.  The almost ten-fold increase in
   flow cache capacity will also be an important improvement -- the
   flow cache should then be able to absorb even the hardest known DoS
   attacks.  We also plan to enhance the design in the direction of
   IPFIX compliance by means of supporting variable record format,
   additional sampling techniques and so on &ldots;
</p>

<seznamknih>

  <kniha id="Ce05">
    Čeleda, P.,  Kováčik, M., Krejčí, R.,
    Kysela, J. and Špringl, P. <i>Software for NetFlow Monitoring
    Adapter.</i> Technical Report XX/2005, CESNET, Praha, 2005.
  </kniha>
  
   <kniha id="Es03">
     Estan, C., Varghese, G.: New directions in traffic measurement
     and accounting: Focusing on the elephants, ignoring the mice. <i>ACM
     Trans. Comput. Syst.</i> 21, 2003.
   </kniha>

   <kniha id="RFC3917">
     Quittek, J., Zseby, T., Claise, B. and Zander, S. <i>Requirements
     for IP Flow Information Export (IPFIX).</i> RFC 3917, IETF, 2004.
   </kniha>

   <kniha id="RFC3954">
     Claise, B. (Ed.). <i>Cisco Systems NetFlow Services Export Version
     9.</i>
   </kniha>
   
   <kniha id="Mo05">
     Molina, M., Chiosi, A., D'Antonio, S. and Ventre, G.:      
     Design principles and algorithms for effective high-speed
     IP flow monitoring. 
     <i>Computer Communications</i>, in press.
   </kniha>
   
   <kniha id="CoHW">
      Liberouter Project. Description of COMBO cards.
      http://www.liberouter.org/hardware.php
    </kniha>

    <kniha id="Ha05">
      Unified Header Specification for NetFlow,
      http://www.liberouter.org/cgi-bin2/cvsweb.cgi/liberouter/vhdl_design/units/hfe/doc/UH-Netflow.txt?rev=1.18
    </kniha>

 </seznamknih>

</zprava>

