[PATCH 11/14] docs: Convert 'formatnwfilter' page to rst

Peter Krempa pkrempa at redhat.com
Wed Apr 13 16:02:12 UTC 2022


From: Pavel Hrdina <phrdina at redhat.com>

Also adjust direct links from other pages.

Signed-off-by: Pavel Hrdina <phrdina at redhat.com>
Signed-off-by: Peter Krempa <pkrempa at redhat.com>
---
 docs/firewall.rst           |    2 +-
 docs/formatdomain.rst       |    3 +-
 docs/formatnwfilter.html.in | 2471 -----------------------------------
 docs/formatnwfilter.rst     | 1789 +++++++++++++++++++++++++
 docs/meson.build            |    2 +-
 5 files changed, 1793 insertions(+), 2474 deletions(-)
 delete mode 100644 docs/formatnwfilter.html.in
 create mode 100644 docs/formatnwfilter.rst

diff --git a/docs/firewall.rst b/docs/firewall.rst
index adda0ef1f4..eff9de5a89 100644
--- a/docs/firewall.rst
+++ b/docs/firewall.rst
@@ -250,7 +250,7 @@ source IP address ``!= $IP`` like this:

 I'm not going to go into details on all the other protocol matches you can do,
 because it'll take far too much space. You can read about the options
-`here <formatnwfilter.html#nwfelemsRulesProto>`__.
+`here <formatnwfilter.html#supported-protocols>`__.

 Out of the box in RHEL6/Fedora rawhide, libvirt ships with a set of default
 useful rules:
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 24fbfd8670..552b5364f8 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -5845,7 +5845,8 @@ complete details.
 The ``filter`` attribute specifies the name of the nwfilter to use. Optional
 ``<parameter>`` elements may be specified for passing additional info to the
 nwfilter via the ``name`` and ``value`` attributes. See the
-`nwfilter <formatnwfilter.html#nwfconceptsvars>`__ docs for info on parameters.
+`nwfilter <formatnwfilter.html#usage-of-variables-in-filters>`__ docs for info
+on parameters.

 :anchor:`<a id="elementsInput"/>`

diff --git a/docs/formatnwfilter.html.in b/docs/formatnwfilter.html.in
deleted file mode 100644
index 04aeda06ec..0000000000
--- a/docs/formatnwfilter.html.in
+++ /dev/null
@@ -1,2471 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE html>
-<html xmlns="http://www.w3.org/1999/xhtml">
-  <body>
-    <h1>Network Filters</h1>
-
-    <ul id="toc">
-    </ul>
-
-    <p>
-      This page provides an introduction to libvirt's network filters,
-      their goals, concepts and XML format.
-    </p>
-
-    <h2><a id="goals">Goals and background</a></h2>
-
-    <p>
-      The goal of the network filtering XML is to enable administrators
-      of a virtualized system to configure and enforce network traffic
-      filtering rules on virtual
-      machines and manage the parameters of network traffic that
-      virtual machines
-      are allowed to send or receive.
-      The network traffic filtering rules are
-      applied on the host when a virtual machine is started. Since the
-      filtering rules
-      cannot be circumvented from within
-      the virtual machine, it makes them mandatory from the point of
-      view of a virtual machine user.
-      <br/><br/>
-      The network filter subsystem allows each virtual machine's network
-      traffic filtering rules to be configured individually on a per
-      interface basis. The rules are
-      applied on the host when the virtual machine is started and can be modified
-      while the virtual machine is running. The latter can be achieved by
-      modifying the XML description of a network filter.
-      <br/><br/>
-      Multiple virtual machines can make use of the same generic network filter.
-      When such a filter is modified, the network traffic filtering rules
-      of all running virtual machines that reference this filter are updated.
-      <br/><br/>
-      Network filtering support is available <span class="since">since 0.8.1
-      (QEMU, KVM)</span>
-    </p>
-
-    <h2><a id="nwfconcepts">Concepts</a></h2>
-    <p>
-      The network traffic filtering subsystem enables configuration
-      of network traffic filtering rules on individual network
-      interfaces that are configured for certain types of
-      network configurations. Supported network types are
-    </p>
-      <ul>
-       <li><code>network</code></li>
-       <li><code>ethernet</code> -- must be used in bridging mode</li>
-       <li><code>bridge</code></li>
-      </ul>
-    <p>
-    The interface XML is used to reference a top-level filter. In the
-    following example, the interface description references
-    the filter <code>clean-traffic</code>.
-    </p>
-<pre>
-...
-<devices>
-  <interface type='bridge'>
-    <mac address='00:16:3e:5d:c7:9e'/>
-    <filterref filter='clean-traffic'/>
-  </interface>
-</devices>
-...</pre>
-
-    <p>
-    Network filters are written in XML and may either contain references
-    to other filters, contain rules for traffic filtering, or
-    hold a combination of both. The above referenced filter
-    <code>clean-traffic </code> is a filter that only contains references to
-    other filters and no actual filtering rules. Since references to
-    other filters can be used, a <i>tree</i> of filters can be built.
-    The <code>clean-traffic</code> filter can be viewed using the
-    command <code>virsh nwfilter-dumpxml clean-traffic</code>.
-    <br/><br/>
-    As previously mentioned, a single network filter can be referenced
-    by multiple virtual machines. Since interfaces will typically
-    have individual parameters associated with their respective traffic
-    filtering rules, the rules described in a filter XML can
-    be parameterized with variables. In this case, the variable name
-    is used in the filter XML and the name and value are provided at the
-    place where the filter is referenced. In the
-    following example, the interface description has been extended with
-    the parameter <code>IP</code> and a dotted IP address as value.
-    </p>
-<pre>
-...
-<devices>
-  <interface type='bridge'>
-    <mac address='00:16:3e:5d:c7:9e'/>
-    <filterref filter='clean-traffic'>
-      <parameter name='IP' value='10.0.0.1'/>
-    </filterref>
-  </interface>
-</devices>
-...</pre>
-
-    <p>
-      In this particular example, the <code>clean-traffic</code> network
-      traffic filter will be instantiated with the IP address parameter
-      10.0.0.1 and enforce that the traffic from this interface will
-      always be using 10.0.0.1 as the source IP address, which is
-      one of the purposes of this particular filter.
-      <br/><br/>
-    </p>
-
-    <h3><a id="nwfconceptschains">Filtering chains</a></h3>
-    <p>
-      Filtering rules are organized in filter chains. These chains can be
-      thought of as having a tree structure with packet
-      filtering rules as entries in individual chains (branches). <br/>
-      Packets start their filter evaluation in the <code>root</code> chain
-      and can then continue their evaluation in other chains, return from
-      those chains back into the <code>root</code> chain or be
-      dropped or accepted by a filtering rule in one of the traversed chains.
-      <br/>
-      Libvirt's network filtering system automatically creates individual
-      <code>root</code> chains for every virtual machine's network interface
-      on which the user chooses to activate traffic filtering.
-      The user may write filtering rules that are either directly instantiated
-      in the <code>root</code> chain or may create protocol-specific
-      filtering chains for efficient evaluation of protocol-specific rules.
-      The following chains exist:
-    </p>
-    <ul>
-     <li>root</li>
-     <li>mac <span class="since">(since 0.9.8)</span></li>
-     <li>stp (spanning tree protocol)
-         <span class="since">(since 0.9.8)</span></li>
-     <li>vlan (802.1Q) <span class="since">(since 0.9.8)</span></li>
-     <li>arp, rarp</li>
-     <li>ipv4</li>
-     <li>ipv6</li>
-    </ul>
-    <p>
-      <span class="since">Since 0.9.8</span> multiple chains evaluating the
-      <code>mac</code>, <code>stp</code>, <code>vlan</code>,
-      <code>arp</code>, <code>rarp</code>, <code>ipv4</code>, or
-      <code>ipv6</code> protocol can be created using
-      the protocol name only as a prefix in the chain's name. This for
-      examples allows chains with names <code>arp-xyz</code> or
-      <code>arp-test</code> to be specified and have ARP protocol packets
-      evaluated in those chains.
-    <br/><br/>
-      The following filter shows an example of filtering ARP traffic
-      in the <code>arp</code> chain.
-    </p>
-<pre>
-<filter name='no-arp-spoofing' chain='arp' priority='-500'>
-  <uuid>f88f1932-debf-4aa1-9fbe-f10d3aa4bc95</uuid>
-  <rule action='drop' direction='out' priority='300'>
-    <mac match='no' srcmacaddr='$MAC'/>
-  </rule>
-  <rule action='drop' direction='out' priority='350'>
-    <arp match='no' arpsrcmacaddr='$MAC'/>
-  </rule>
-  <rule action='drop' direction='out' priority='400'>
-    <arp match='no' arpsrcipaddr='$IP'/>
-  </rule>
-  <rule action='drop' direction='in' priority='450'>
-    <arp opcode='Reply'/>
-    <arp match='no' arpdstmacaddr='$MAC'/>
-  </rule>
-  <rule action='drop' direction='in' priority='500'>
-    <arp match='no' arpdstipaddr='$IP'/>
-  </rule>
-  <rule action='accept' direction='inout' priority='600'>
-    <arp opcode='Request'/>
-  </rule>
-  <rule action='accept' direction='inout' priority='650'>
-    <arp opcode='Reply'/>
-  </rule>
-  <rule action='drop' direction='inout' priority='1000'/>
-</filter>
-</pre>
-    <p>
-      The consequence of putting ARP-specific rules in the <code>arp</code>
-      chain, rather than for example in the <code>root</code> chain, is that
-      packets for any other protocol than ARP do not need to be evaluated by
-      ARP protocol-specific rules. This improves the efficiency
-      of the traffic filtering. However, one must then pay attention to only
-      put filtering rules for the given protocol into the chain since
-      any other rules will not be evaluated, i.e., an IPv4 rule will not
-      be evaluated in the ARP chain since no IPv4 protocol packets will
-      traverse the ARP chain.
-      <br/><br/>
-    </p>
-    <h3><a id="nwfconceptschainpriorities">Filtering chain priorities</a></h3>
-    <p>
-      All chains are connected to the <code>root</code> chain. The order in
-      which those chains are accessed is influenced by the priority of the
-      chain. The following table shows the chains that can be assigned a
-      priority and their default priorities.
-    </p>
-      <table class="top_table">
-       <tr>
-         <th> Chain (prefix) </th>
-         <th> Default priority </th>
-       </tr>
-       <tr>
-         <td>stp</td><td>-810</td>
-       </tr>
-       <tr>
-         <td>mac</td><td>-800</td>
-       </tr>
-       <tr>
-         <td>vlan</td><td>-750</td>
-       </tr>
-       <tr>
-         <td>ipv4</td><td>-700</td>
-       </tr>
-       <tr>
-         <td>ipv6</td><td>-600</td>
-       </tr>
-       <tr>
-         <td>arp</td><td>-500</td>
-       </tr>
-       <tr>
-         <td>rarp</td><td>-400</td>
-       </tr>
-      </table>
-    <p>
-      A chain with a lower priority value is accessed before one with a
-      higher value.
-      <br/>
-      <span class="since">Since 0.9.8</span> the above listed chains
-      can be assigned custom priorities by writing a value in the
-      range [-1000, 1000] into the priority (XML) attribute in the filter
-      node. The above example filter shows the default priority of -500
-      for <code>arp</code> chains.
-    </p>
-    <h3><a id="nwfconceptsvars">Usage of variables in filters</a></h3>
-    <p>
-
-      Two variables names have so far been reserved for usage by the
-      network traffic filtering subsystem: <code>MAC</code> and
-      <code>IP</code>.
-      <br/><br/>
-      <code>MAC</code> is the MAC address of the
-      network interface. A filtering rule that references this variable
-      will automatically be instantiated with the MAC address of the
-      interface. This works without the user having to explicitly provide
-      the MAC parameter. Even though it is possible to specify the MAC
-      parameter similar to the IP parameter above, it is discouraged
-      since libvirt knows what MAC address an interface will be using.
-      <br/><br/>
-      The parameter <code>IP</code> represents the IP address
-      that the operating system inside the virtual machine is expected
-      to use on the given interface. The <code>IP</code> parameter
-      is special in so far as the libvirt daemon will try to determine
-      the IP address (and thus the IP parameter's value) that is being
-      used on an interface if the parameter
-      is not explicitly provided but referenced.
-      For current limitations on IP address detection, consult the
-      <a href="#nwflimits">section on limitations</a> on how to use this
-      feature and what to expect when using it.
-      <br/><br/>
-      The above-shown network filer <code>no-arp-spoofing</code>
-      is an example of
-      a network filter XML referencing the <code>MAC</code> and
-      <code>IP</code> variables.
-      <br/><br/>
-      Note that referenced variables are always prefixed with the
-      $ (dollar) sign. The format of the value of a variable
-      must be of the type expected by the filter attribute in the
-      XML. In the above example, the <code>IP</code> parameter
-      must hold a dotted IP address in decimal numbers format.
-      Failure to  provide the correct
-      value type will result in the filter not being instantiatable
-      and will prevent a virtual machine from starting or the
-      interface from attaching when hotplugging is used. The types
-      that are expected for each XML attribute are shown
-      below.
-      <br/><br/>
-      <span class="since">Since 0.9.8</span> variables can contain lists of
-      elements, e.g., the variable <code>IP</code> can contain multiple IP
-      addresses that are valid on a particular interface. The notation for
-      providing multiple elements for the IP variable is:
-    </p>
-<pre>
-...
-<devices>
-  <interface type='bridge'>
-    <mac address='00:16:3e:5d:c7:9e'/>
-    <filterref filter='clean-traffic'>
-      <parameter name='IP' value='10.0.0.1'/>
-      <parameter name='IP' value='10.0.0.2'/>
-      <parameter name='IP' value='10.0.0.3'/>
-    </filterref>
-  </interface>
-</devices>
-...</pre>
-    <p>
-      This then allows filters to enable multiple IP addresses
-      per interface. Therefore, with the list
-      of IP address shown above, the following rule will create 3
-      individual filtering rules, one for each IP address.
-    </p>
-<pre>
-...
-<rule action='accept' direction='in' priority='500'>
-  <tcp srpipaddr='$IP'/>
-</rule>
-...
-</pre>
-    <p>
-      <span class="since">Since 0.9.10</span> it is possible to access
-      individual elements of a variable holding a list of elements.
-      A filtering rule like the following accesses the 2nd element
-      of the variable DSTPORTS.
-    </p>
-<pre>
-...
-<rule action='accept' direction='in' priority='500'>
-  <udp dstportstart='$DSTPORTS[1]'/>
-</rule>
-...
-</pre>
-    <p>
-      <span class="since">Since 0.9.10</span> it is possible to create
-      filtering rules that instantiate all combinations of rules from
-      different lists using the notation of
-      <code>$VARIABLE[@<iterator ID>]</code>.
-      The following rule allows a virtual machine to
-      receive traffic on a set of ports, which are specified in DSTPORTS,
-      from the set of source IP address specified in SRCIPADDRESSES.
-      The rule generates all combinations of elements of the variable
-      DSTPORT with those of SRCIPADDRESSES by using two independent
-      iterators to access their elements.
-    </p>
-<pre>
-...
-<rule action='accept' direction='in' priority='500'>
-  <ip srcipaddr='$SRCIPADDRESSES[@1]' dstportstart='$DSTPORTS[@2]'/>
-</rule>
-...
-</pre>
-
-    <p>
-      In an example we assign concrete values to SRCIPADDRESSES and DSTPORTS
-    </p>
-<pre>
-SRCIPADDRESSES = [ 10.0.0.1, 11.1.2.3 ]
-DSTPORTS = [ 80, 8080 ]
-</pre>
-    <p>
-      Accessing the variables using $SRCIPADDRESSES[@1] and $DSTPORTS[@2] would
-      then result in all combinations of addresses and ports being created:
-    </p>
-<pre>
-10.0.0.1, 80
-10.0.0.1, 8080
-11.1.2.3, 80
-11.1.2.3, 8080
-</pre>
-    <p>
-      Accessing the same variables using a single iterator, for example by using
-      the notation $SRCIPADDRESSES[@1] and $DSTPORTS[@1], would result in
-      parallel access to both lists and result in the following combinations:
-    </p>
-<pre>
-10.0.0.1, 80
-11.1.2.3, 8080
-</pre>
-    <p>
-      Further, the notation of $VARIABLE is short-hand for $VARIABLE[@0]. The
-      former notation always assumes the iterator with Id '0'.
-    </p>
-
-    <h3><a id="nwfelemsRulesAdvIPAddrDetection">Automatic IP address detection</a></h3>
-    <p>
-       The detection of IP addresses used on a virtual machine's interface
-       is automatically activated if the variable <code>IP</code> is referenced
-       but no value has been assigned to it.
-       <span class="since">Since 0.9.13</span>
-       the variable <code>CTRL_IP_LEARNING</code> can be used to specify
-       the IP address learning method to use. Valid values are <code>any</code>,
-       <code>dhcp</code>, or <code>none</code>.
-       <br/><br/>
-       The value <code>any</code> means that libvirt may use any packet to
-       determine the address in use by a virtual machine, which is the default
-       behavior if the variable <code>CTRL_IP_LEARNING</code> is not set. This method
-       will only detect a single IP address on an interface.
-       Once a VM's IP address has been detected, its IP network traffic
-       will be locked to that address, if for example IP address spoofing
-       is prevented by one of its filters. In that case the user of the VM
-       will not be able to change the IP address on the interface inside
-       the VM, which would be considered IP address spoofing.
-       When a VM is migrated to another host or resumed after a suspend operation,
-       the first packet sent by the VM will again determine the IP address it can
-       use on a particular interface.
-       <br/>
-       A value of <code>dhcp</code> specifies that libvirt should only honor DHCP
-       server-assigned addresses with valid leases. This method supports the detection
-       and usage of multiple IP address per interface.
-       When a VM is resumed after a suspend operation, still valid IP address leases
-       are applied to its filters. Otherwise the VM is expected to again use DHCP to obtain new
-       IP addresses. The migration of a VM to another physical host requires that
-       the VM again runs the DHCP protocol.
-       <br/><br/>
-       Use of <code>CTRL_IP_LEARNING=dhcp</code> (DHCP snooping) provides additional
-       anti-spoofing security, especially when combined with a filter allowing
-       only trusted DHCP servers to assign addresses. To enable this, set the
-       variable <code>DHCPSERVER</code> to the IP address of a valid DHCP server
-       and provide filters that use this variable to filter incoming DHCP responses.
-       <br/><br/>
-       When DHCP snooping is enabled and the DHCP lease expires,
-       the VM will no longer be able to use the IP address until it acquires a
-       new, valid lease from a DHCP server. If the VM is migrated, it must get
-       a new valid DHCP lease to use an IP address (e.g., by
-       bringing the VM interface down and up again).
-       <br/><br/>
-       Note that automatic DHCP detection listens to the DHCP traffic
-       the VM exchanges with the DHCP server of the infrastructure. To avoid
-       denial-of-service attacks on libvirt, the evaluation of those packets
-       is rate-limited, meaning that a VM sending an excessive number of DHCP
-       packets per second on an interface will not have all of those packets
-       evaluated and thus filters may not get adapted. Normal DHCP client
-       behavior is assumed to send a low number of DHCP packets per second.
-       Further, it is important to setup appropriate filters on all VMs in
-       the infrastructure to avoid them  being able to send DHCP
-       packets. Therefore VMs must either be prevented from sending UDP and TCP
-       traffic from port 67 to port 68 or the <code>DHCPSERVER</code>
-       variable should be used on all VMs to restrict DHCP server messages to
-       only be allowed to originate from trusted DHCP servers. At the same
-       time anti-spoofing prevention must be enabled on all VMs in the subnet.
-       <br/><br/>
-       If <code>CTRL_IP_LEARNING</code> is set to <code>none</code>, libvirt does not do
-       IP address learning and referencing <code>IP</code> without assigning it an
-       explicit value is an error.
-       <br/><br/>
-       The following XML provides an example for the activation of IP address learning
-       using the DHCP snooping method:
-    </p>
-<pre>
-<interface type='bridge'>
-  <source bridge='virbr0'/>
-  <filterref filter='clean-traffic'>
-    <parameter name='CTRL_IP_LEARNING' value='dhcp'/>
-  </filterref>
-</interface>
-</pre>
-
-    <h3><a id="nwfelemsReservedVars">Reserved Variables</a></h3>
-    <p>
-      The following table lists reserved variables in use by libvirt.
-    </p>
-      <table class="top_table">
-       <tr>
-         <th> Variable Name </th>
-         <th> Semantics </th>
-       </tr>
-       <tr>
-         <td> MAC </td>
-         <td> The MAC address of the interface </td>
-       </tr>
-       <tr>
-         <td> IP </td>
-         <td> The list of IP addresses in use by an interface </td>
-       </tr>
-       <tr>
-         <td> IPV6 </td>
-         <td> The list of IPV6 addresses in use by an interface </td>
-       </tr>
-       <tr>
-         <td> DHCPSERVER </td>
-         <td> The list of IP addresses of trusted DHCP servers</td>
-       </tr>
-       <tr>
-         <td> DHCPSERVERV6 </td>
-         <td> Not currently implemented:
-              The list of IPv6 addresses of trusted DHCP servers</td>
-       </tr>
-       <tr>
-         <td> CTRL_IP_LEARNING </td>
-         <td> The choice of the IP address detection mode </td>
-       </tr>
-      </table>
-
-    <h2><a id="nwfelems">Element and attribute overview</a></h2>
-
-    <p>
-      The root element required for all network filters is
-      named <code>filter</code> with two possible attributes. The
-      <code>name</code> attribute provides a unique name of the
-      given filter. The <code>chain</code> attribute is optional but
-      allows certain filters to be better organized for more efficient
-      processing by the firewall subsystem of the underlying host.
-      Currently the system only supports the chains <code>root,
-      ipv4, ipv6, arp and rarp</code>.
-    </p>
-
-    <h3><a id="nwfelemsRefs">References to other filters</a></h3>
-    <p>
-     Any filter may hold references to other filters. Individual
-     filters may be referenced multiple times in a filter tree but
-     references between filters must not introduce loops (directed
-     acyclic graph).
-     <br/><br/>
-     The following shows the XML of the <code>clean-traffic</code>
-     network filter referencing several other filters.
-    </p>
-<pre>
-<filter name='clean-traffic'>
-  <uuid>6ef53069-ba34-94a0-d33d-17751b9b8cb1</uuid>
-  <filterref filter='no-mac-spoofing'/>
-  <filterref filter='no-ip-spoofing'/>
-  <filterref filter='allow-incoming-ipv4'/>
-  <filterref filter='no-arp-spoofing'/>
-  <filterref filter='no-other-l2-traffic'/>
-  <filterref filter='qemu-announce-self'/>
-</filter>
-</pre>
-
-    <p>
-    To reference another filter, the XML node <code>filterref</code>
-    needs to be provided inside a <code>filter</code> node. This
-    node must have the attribute <code>filter</code> whose value contains
-    the name of the filter to be referenced.
-    <br/><br/>
-    New network filters can be defined at any time and
-    may contain references to network filters that are
-    not known to libvirt, yet. However, once a virtual machine
-    is started or a network interface
-    referencing a filter is to be hotplugged, all network filters
-    in the filter tree must be available. Otherwise the virtual
-    machine will not start or the network interface cannot be
-    attached.
-    </p>
-
-    <h3><a id="nwfelemsRules">Filter rules</a></h3>
-    <p>
-    The following XML shows a simple example of a network
-    traffic filter implementing a rule to drop traffic if
-    the IP address (provided through the value of the
-    variable IP) in an outgoing IP packet is not the expected
-    one, thus preventing IP address spoofing by the VM.
-    </p>
-<pre>
-<filter name='no-ip-spoofing' chain='ipv4'>
-  <uuid>fce8ae33-e69e-83bf-262e-30786c1f8072</uuid>
-  <rule action='drop' direction='out' priority='500'>
-    <ip match='no' srcipaddr='$IP'/>
-  </rule>
-</filter>
-</pre>
-
-    <p>
-     A traffic filtering rule starts with the <code>rule</code>
-     node. This node may contain up to three attributes
-    </p>
-    <ul>
-     <li>
-        action -- mandatory; must either be <code>drop</code>
-        (matching the rule silently discards the packet with no
-        further analysis),
-        <code>reject</code> (matching the rule generates an ICMP
-        reject message with no further analysis) <span class="since">(since
-        0.9.0)</span>, <code>accept</code> (matching the rule accepts
-        the packet with no further analysis), <code>return</code>
-        (matching the rule passes this filter, but returns control to
-        the calling filter for further
-        analysis) <span class="since">(since 0.9.7)</span>,
-        or <code>continue</code> (matching the rule goes on to the next
-        rule for further analysis) <span class="since">(since
-        0.9.7)</span>.
-     </li>
-     <li>
-        direction -- mandatory; must either be <code>in</code>, <code>out</code> or
-         <code>inout</code> if the rule is for incoming,
-         outgoing or incoming-and-outgoing traffic
-     </li>
-     <li>
-        priority -- optional; the priority of the rule controls the order in
-        which the rule will be instantiated relative to other rules.
-        Rules with lower value will be instantiated before rules with higher
-        values.
-        Valid values are in the range of 0 to 1000.
-        <span class="since">Since 0.9.8</span> this has been extended to cover
-        the range of -1000 to 1000. If this attribute is not
-        provided, priority 500 will automatically be assigned.
-        <br/>
-        Note that filtering rules in the <code>root</code> chain are sorted
-        with filters connected to the <code>root</code> chain following
-        their priorities. This allows to interleave filtering rules with
-        access to filter chains.
-        (See also section on
-         <a href="#nwfconceptschainpriorities">
-           filtering chain priorities
-         </a>.)
-     </li>
-     <li>
-        statematch -- optional; possible values are '0' or 'false' to
-        turn the underlying connection state matching off; default is 'true'
-        <br/>
-        Also read the section on <a href="#nwfelemsRulesAdv">advanced configuration</a>
-        topics.
-     </li>
-    </ul>
-    <p>
-     The above example indicates that the traffic of type <code>ip</code>
-     will be associated with the chain 'ipv4' and the rule will have
-     priority 500. If for example another filter is referenced whose
-     traffic of type <code>ip</code> is also associated with the chain
-     'ipv4' then that filter's rules will be ordered relative to the priority
-     500 of the shown rule.
-     <br/><br/>
-     A rule may contain a single rule for filtering of traffic. The
-     above example shows that traffic of type <code>ip</code> is to be
-     filtered.
-    </p>
-
-    <h4><a id="nwfelemsRulesProto">Supported protocols</a></h4>
-    <p>
-     The following sections enumerate the list of protocols that
-     are supported by the network filtering subsystem. The
-     type of traffic a rule is supposed to filter on is provided
-     in the <code>rule</code> node as a nested node. Depending
-     on the traffic type a rule is filtering, the attributes are
-     different. The above example showed the single
-     attribute <code>srcipaddr</code> that is valid inside the
-     <code>ip</code> traffic filtering node. The following sections
-     show what attributes are valid and what type of data they are
-     expecting. The following datatypes are available:
-    </p>
-    <ul>
-     <li>UINT8 : 8 bit integer; range 0-255</li>
-     <li>UINT16: 16 bit integer; range 0-65535</li>
-     <li>MAC_ADDR: MAC address in dotted decimal format, i.e., 00:11:22:33:44:55</li>
-     <li>MAC_MASK: MAC address mask in MAC address format, i.e., FF:FF:FF:FC:00:00</li>
-     <li>IP_ADDR: IP address in dotted decimal format, i.e., 10.1.2.3</li>
-     <li>IP_MASK: IP address mask in either dotted decimal format (255.255.248.0) or CIDR mask (0-32)</li>
-     <li>IPV6_ADDR: IPv6 address in numbers format, i.e., FFFF::1</li>
-     <li>IPV6_MASK: IPv6 mask in numbers format (FFFF:FFFF:FC00::) or CIDR mask (0-128)</li>
-     <li>STRING: A string</li>
-     <li>BOOLEAN: 'true', 'yes', '1' or 'false', 'no', '0'</li>
-     <li>IPSETFLAGS: The source and destination flags of the ipset described
-         by up to 6 'src' or 'dst' elements selecting features from either
-         the source or destination part of the packet header; example:
-         src,src,dst. The number of 'selectors' to provide here depends
-         on the type of ipset that is referenced.</li>
-    </ul>
-    <p>
-     <br/><br/>
-     Every attribute except for those of type IP_MASK or IPV6_MASK can
-     be negated using the <code>match</code>
-     attribute with value <code>no</code>. Multiple negated attributes
-     may be grouped together. The following
-     XML fragment shows such an example using abstract attributes.
-    </p>
-<pre>
-[...]
-<rule action='drop' direction='in'>
-  <protocol match='no' attribute1='value1' attribute2='value2'/>
-  <protocol attribute3='value3'/>
-</rule>
-[...]
-</pre>
-    <p>
-     Rules perform a logical AND evaluation on all values of the given
-     protocol attributes. Thus, if a single attribute's value does not match
-     the one given in the rule, the whole rule will be skipped during
-     evaluation. Therefore, in the above example incoming traffic
-     will only be dropped if
-     the protocol property attribute1 does not match value1 AND
-     the protocol property attribute2 does not match value2 AND
-     the protocol property attribute3 matches value3.
-     <br/><br/>
-    </p>
-
-
-    <h5><a id="nwfelemsRulesProtoMAC">MAC (Ethernet)</a></h5>
-    <p>
-      Protocol ID: <code>mac</code>
-      <br/>
-      Note: Rules of this type should go into the <code>root</code> chain.
-    </p>
-      <table class="top_table">
-       <tr>
-         <th> Attribute </th>
-         <th> Datatype </th>
-         <th> Semantics </th>
-       </tr>
-       <tr>
-         <td>srcmacaddr</td>
-         <td>MAC_ADDR</td>
-         <td>MAC address of sender</td>
-       </tr>
-       <tr>
-         <td>srcmacmask</td>
-         <td>MAC_MASK</td>
-         <td>Mask applied to MAC address of sender</td>
-       </tr>
-       <tr>
-         <td>dstmacaddr</td>
-         <td>MAC_ADDR</td>
-         <td>MAC address of destination</td>
-       </tr>
-       <tr>
-         <td>dstmacmask</td>
-         <td>MAC_MASK</td>
-         <td>Mask applied to MAC address of destination</td>
-       </tr>
-       <tr>
-         <td>protocolid</td>
-         <td>UINT16 (0x600-0xffff), STRING</td>
-         <td>Layer 3 protocol ID</td>
-       </tr>
-       <tr>
-         <td>comment <span class="since">(Since 0.8.5)</span></td>
-         <td>STRING</td>
-         <td>text with max. 256 characters</td>
-       </tr>
-      </table>
-    <p>
-      Valid Strings for <code>protocolid</code> are: arp, rarp, ipv4, ipv6
-    </p>
-<pre>
-[...]
-<mac match='no' srcmacaddr='$MAC'/>
-[...]
-</pre>
-
-    <h5><a id="nwfelemsRulesProtoVLAN">VLAN (802.1Q)</a>
-      <span class="since">(Since 0.9.8)</span>
-    </h5>
-    <p>
-      Protocol ID: <code>vlan</code>
-      <br/>
-      Note: Rules of this type should go either into the <code>root</code> or
-      <code>vlan</code> chain.
-    </p>
-      <table class="top_table">
-       <tr>
-         <th> Attribute </th>
-         <th> Datatype </th>
-         <th> Semantics </th>
-       </tr>
-       <tr>
-         <td>srcmacaddr</td>
-         <td>MAC_ADDR</td>
-         <td>MAC address of sender</td>
-       </tr>
-       <tr>
-         <td>srcmacmask</td>
-         <td>MAC_MASK</td>
-         <td>Mask applied to MAC address of sender</td>
-       </tr>
-       <tr>
-         <td>dstmacaddr</td>
-         <td>MAC_ADDR</td>
-         <td>MAC address of destination</td>
-       </tr>
-       <tr>
-         <td>dstmacmask</td>
-         <td>MAC_MASK</td>
-         <td>Mask applied to MAC address of destination</td>
-       </tr>
-       <tr>
-         <td>vlanid</td>
-         <td>UINT16 (0x0-0xfff, 0 - 4095)</td>
-         <td>VLAN ID</td>
-       </tr>
-       <tr>
-         <td>encap-protocol</td>
-         <td>UINT16 (0x03c-0xfff), String</td>
-         <td>Encapsulated layer 3 protocol ID</td>
-       </tr>
-       <tr>
-         <td>comment </td>
-         <td>STRING</td>
-         <td>text with max. 256 characters</td>
-       </tr>
-      </table>
-    <p>
-      Valid Strings for <code>encap-protocol</code> are: arp, ipv4, ipv6
-    </p>
-
-    <h5><a id="nwfelemsRulesProtoSTP">STP (Spanning Tree Protocol)</a>
-      <span class="since">(Since 0.9.8)</span>
-    </h5>
-    <p>
-      Protocol ID: <code>stp</code>
-      <br/>
-      Note: Rules of this type should go either into the <code>root</code> or
-      <code>stp</code> chain.
-    </p>
-      <table class="top_table">
-       <tr>
-         <th> Attribute </th>
-         <th> Datatype </th>
-         <th> Semantics </th>
-       </tr>
-       <tr>
-         <td>srcmacaddr</td>
-         <td>MAC_ADDR</td>
-         <td>MAC address of sender</td>
-       </tr>
-       <tr>
-         <td>srcmacmask</td>
-         <td>MAC_MASK</td>
-         <td>Mask applied to MAC address of sender</td>
-       </tr>
-       <tr>
-         <td>type</td>
-         <td>UINT8</td>
-         <td>Bridge Protocol Data Unit (BPDU) type</td>
-       </tr>
-       <tr>
-         <td>flags</td>
-         <td>UINT8</td>
-         <td>BPDU flag</td>
-       </tr>
-       <tr>
-         <td>root-priority</td>
-         <td>UINT16</td>
-         <td>Root priority (range start)</td>
-       </tr>
-       <tr>
-         <td>root-priority-hi</td>
-         <td>UINT16</td>
-         <td>Root priority range end</td>
-       </tr>
-       <tr>
-         <td>root-address</td>
-         <td>MAC_ADDRESS</td>
-         <td>Root MAC address</td>
-       </tr>
-       <tr>
-         <td>root-address-mask</td>
-         <td>MAC_MASK</td>
-         <td>Root MAC address mask</td>
-       </tr>
-       <tr>
-         <td>root-cost</td>
-         <td>UINT32</td>
-         <td>Root path cost (range start)</td>
-       </tr>
-       <tr>
-         <td>root-cost-hi</td>
-         <td>UINT32</td>
-         <td>Root path cost range end</td>
-       </tr>
-       <tr>
-         <td>sender-priority</td>
-         <td>UINT16</td>
-         <td>Sender priority (range start)</td>
-       </tr>
-       <tr>
-         <td>sender-priority-hi</td>
-         <td>UINT16</td>
-         <td>Sender priority range end</td>
-       </tr>
-       <tr>
-         <td>sender-address</td>
-         <td>MAC_ADDRESS</td>
-         <td>BPDU sender MAC address</td>
-       </tr>
-       <tr>
-         <td>sender-address-mask</td>
-         <td>MAC_MASK</td>
-         <td>BPDU sender MAC address mask</td>
-       </tr>
-       <tr>
-         <td>port</td>
-         <td>UINT16</td>
-         <td>Port identifier (range start)</td>
-       </tr>
-       <tr>
-         <td>port_hi</td>
-         <td>UINT16</td>
-         <td>Port identifier range end</td>
-       </tr>
-       <tr>
-         <td>msg-age</td>
-         <td>UINT16</td>
-         <td>Message age timer (range start)</td>
-       </tr>
-       <tr>
-         <td>msg-age-hi</td>
-         <td>UINT16</td>
-         <td>Message age timer range end</td>
-       </tr>
-       <tr>
-         <td>max-age</td>
-         <td>UINT16</td>
-         <td>Maximum age timer (range start)</td>
-       </tr>
-       <tr>
-         <td>max-age-hi</td>
-         <td>UINT16</td>
-         <td>Maximum age timer range end</td>
-       </tr>
-       <tr>
-         <td>hello-time</td>
-         <td>UINT16</td>
-         <td>Hello time timer (range start)</td>
-       </tr>
-       <tr>
-         <td>hello-time-hi</td>
-         <td>UINT16</td>
-         <td>Hello time timer range end</td>
-       </tr>
-       <tr>
-         <td>forward-delay</td>
-         <td>UINT16</td>
-         <td>Forward delay (range start)</td>
-       </tr>
-       <tr>
-         <td>forward-delay-hi</td>
-         <td>UINT16</td>
-         <td>Forward delay range end</td>
-       </tr>
-       <tr>
-         <td>comment</td>
-         <td>STRING</td>
-         <td>text with max. 256 characters</td>
-       </tr>
-      </table>
-
-    <h5><a id="nwfelemsRulesProtoARP">ARP/RARP</a></h5>
-    <p>
-      Protocol ID: <code>arp</code> or <code>rarp</code>
-      <br/>
-      Note: Rules of this type should either go into the
-      <code>root</code> or <code>arp/rarp</code> chain.
-    </p>
-      <table class="top_table">
-       <tr>
-         <th> Attribute </th>
-         <th> Datatype </th>
-         <th> Semantics </th>
-       </tr>
-       <tr>
-         <td>srcmacaddr</td>
-         <td>MAC_ADDR</td>
-         <td>MAC address of sender</td>
-       </tr>
-       <tr>
-         <td>srcmacmask</td>
-         <td>MAC_MASK</td>
-         <td>Mask applied to MAC address of sender</td>
-       </tr>
-       <tr>
-         <td>dstmacaddr</td>
-         <td>MAC_ADDR</td>
-         <td>MAC address of destination</td>
-       </tr>
-       <tr>
-         <td>dstmacmask</td>
-         <td>MAC_MASK</td>
-         <td>Mask applied to MAC address of destination</td>
-       </tr>
-       <tr>
-         <td>hwtype</td>
-         <td>UINT16</td>
-         <td>Hardware type</td>
-       </tr>
-       <tr>
-         <td>protocoltype</td>
-         <td>UINT16</td>
-         <td>Protocol type</td>
-       </tr>
-       <tr>
-         <td>opcode</td>
-         <td>UINT16, STRING</td>
-         <td>Opcode</td>
-       </tr>
-       <tr>
-         <td>arpsrcmacaddr</td>
-         <td>MAC_ADDR</td>
-         <td>Source MAC address in ARP/RARP packet</td>
-       </tr>
-       <tr>
-         <td>arpdstmacaddr</td>
-         <td>MAC_ADDR</td>
-         <td>Destination MAC address in ARP/RARP packet</td>
-       </tr>
-       <tr>
-         <td>arpsrcipaddr</td>
-         <td>IP_ADDR</td>
-         <td>Source IP address in ARP/RARP packet</td>
-       </tr>
-       <tr>
-         <td>arpsrcipmask <span class="since">(Since 1.2.3)</span></td>
-         <td>IP_MASK</td>
-         <td>Source IP mask</td>
-       </tr>
-       <tr>
-         <td>arpdstipaddr</td>
-         <td>IP_ADDR</td>
-         <td>Destination IP address in ARP/RARP packet</td>
-       </tr>
-       <tr>
-         <td>arpdstipmask <span class="since">(Since 1.2.3)</span></td>
-         <td>IP_MASK</td>
-         <td>Destination IP mask</td>
-       </tr>
-       <tr>
-         <td>comment <span class="since">(Since 0.8.5)</span></td>
-         <td>STRING</td>
-         <td>text with max. 256 characters</td>
-       </tr>
-       <tr>
-         <td>gratuitous <span class="since">(Since 0.9.2)</span></td>
-         <td>BOOLEAN</td>
-         <td>boolean indicating whether to check for gratuitous ARP packet</td>
-       </tr>
-      </table>
-    <p>
-      Valid strings for the <code>Opcode</code> field are:
-       Request, Reply, Request_Reverse, Reply_Reverse, DRARP_Request,
-       DRARP_Reply, DRARP_Error, InARP_Request, ARP_NAK
-      <br/><br/>
-    </p>
-
-    <h5><a id="nwfelemsRulesProtoIP">IPv4</a></h5>
-    <p>
-      Protocol ID: <code>ip</code>
-      <br/>
-      Note: Rules of this type should either go into the
-      <code>root</code> or <code>ipv4</code> chain.
-    </p>
-      <table class="top_table">
-       <tr>
-         <th> Attribute </th>
-         <th> Datatype </th>
-         <th> Semantics </th>
-       </tr>
-       <tr>
-         <td>srcmacaddr</td>
-         <td>MAC_ADDR</td>
-         <td>MAC address of sender</td>
-       </tr>
-       <tr>
-         <td>srcmacmask</td>
-         <td>MAC_MASK</td>
-         <td>Mask applied to MAC address of sender</td>
-       </tr>
-       <tr>
-         <td>dstmacaddr</td>
-         <td>MAC_ADDR</td>
-         <td>MAC address of destination</td>
-       </tr>
-       <tr>
-         <td>dstmacmask</td>
-         <td>MAC_MASK</td>
-         <td>Mask applied to MAC address of destination</td>
-       </tr>
-       <tr>
-         <td>srcipaddr</td>
-         <td>IP_ADDR</td>
-         <td>Source IP address</td>
-       </tr>
-       <tr>
-         <td>srcipmask</td>
-         <td>IP_MASK</td>
-         <td>Mask applied to source IP address</td>
-       </tr>
-       <tr>
-         <td>dstipaddr</td>
-         <td>IP_ADDR</td>
-         <td>Destination IP address</td>
-       </tr>
-       <tr>
-         <td>dstipmask</td>
-         <td>IP_MASK</td>
-         <td>Mask applied to destination IP address</td>
-       </tr>
-       <tr>
-         <td>protocol</td>
-         <td>UINT8, STRING</td>
-         <td>Layer 4 protocol identifier</td>
-       </tr>
-       <tr>
-         <td>srcportstart</td>
-         <td>UINT16</td>
-         <td>Start of range of valid source ports; requires <code>protocol</code></td>
-       </tr>
-       <tr>
-         <td>srcportend</td>
-         <td>UINT16</td>
-         <td>End of range of valid source ports; requires <code>protocol</code></td>
-       </tr>
-       <tr>
-         <td>dstportstart</td>
-         <td>UINT16</td>
-         <td>Start of range of valid destination ports; requires <code>protocol</code></td>
-       </tr>
-       <tr>
-         <td>dstportend</td>
-         <td>UINT16</td>
-         <td>End of range of valid destination ports; requires <code>protocol</code></td>
-       </tr>
-       <tr>
-         <td>dscp</td>
-         <td>UINT8 (0x0-0x3f, 0 - 63)</td>
-         <td>Differentiated Services Code Point</td>
-       </tr>
-       <tr>
-         <td>comment <span class="since">(Since 0.8.5)</span></td>
-         <td>STRING</td>
-         <td>text with max. 256 characters</td>
-       </tr>
-      </table>
-    <p>
-      Valid strings for <code>protocol</code> are:
-         tcp, udp, udplite, esp, ah, icmp, igmp, sctp
-      <br/><br/>
-    </p>
-
-
-    <h5><a id="nwfelemsRulesProtoIPv6">IPv6</a></h5>
-    <p>
-      Protocol ID: <code>ipv6</code>
-      <br/>
-      Note: Rules of this type should either go into the
-      <code>root</code> or <code>ipv6</code> chain.
-    </p>
-      <table class="top_table">
-       <tr>
-         <th> Attribute </th>
-         <th> Datatype </th>
-         <th> Semantics </th>
-       </tr>
-       <tr>
-         <td>srcmacaddr</td>
-         <td>MAC_ADDR</td>
-         <td>MAC address of sender</td>
-       </tr>
-       <tr>
-         <td>srcmacmask</td>
-         <td>MAC_MASK</td>
-         <td>Mask applied to MAC address of sender</td>
-       </tr>
-       <tr>
-         <td>dstmacaddr</td>
-         <td>MAC_ADDR</td>
-         <td>MAC address of destination</td>
-       </tr>
-       <tr>
-         <td>dstmacmask</td>
-         <td>MAC_MASK</td>
-         <td>Mask applied to MAC address of destination</td>
-       </tr>
-       <tr>
-         <td>srcipaddr</td>
-         <td>IPV6_ADDR</td>
-         <td>Source IPv6 address</td>
-       </tr>
-       <tr>
-         <td>srcipmask</td>
-         <td>IPV6_MASK</td>
-         <td>Mask applied to source IPv6 address</td>
-       </tr>
-       <tr>
-         <td>dstipaddr</td>
-         <td>IPV6_ADDR</td>
-         <td>Destination IPv6 address</td>
-       </tr>
-       <tr>
-         <td>dstipmask</td>
-         <td>IPV6_MASK</td>
-         <td>Mask applied to destination IPv6 address</td>
-       </tr>
-       <tr>
-         <td>protocol</td>
-         <td>UINT8</td>
-         <td>Layer 4 protocol identifier</td>
-       </tr>
-       <tr>
-         <td>srcportstart</td>
-         <td>UINT16</td>
-         <td>Start of range of valid source ports; requires <code>protocol</code></td>
-       </tr>
-       <tr>
-         <td>srcportend</td>
-         <td>UINT16</td>
-         <td>End of range of valid source ports; requires <code>protocol</code></td>
-       </tr>
-       <tr>
-         <td>dstportstart</td>
-         <td>UINT16</td>
-         <td>Start of range of valid destination ports; requires <code>protocol</code></td>
-       </tr>
-       <tr>
-         <td>dstportend</td>
-         <td>UINT16</td>
-         <td>End of range of valid destination ports; requires <code>protocol</code></td>
-       </tr>
-       <tr>
-         <td>type<span class="since">(Since 1.2.12)</span></td>
-         <td>UINT8</td>
-         <td>ICMPv6 type; requires <code>protocol</code> to be set to <code>icmpv6</code></td>
-       </tr>
-       <tr>
-         <td>typeend<span class="since">(Since 1.2.12)</span></td>
-         <td>UINT8</td>
-         <td>ICMPv6 type end of range; requires <code>protocol</code> to be set to <code>icmpv6</code></td>
-       </tr>
-       <tr>
-         <td>code<span class="since">(Since 1.2.12)</span></td>
-         <td>UINT8</td>
-         <td>ICMPv6 code; requires <code>protocol</code> to be set to <code>icmpv6</code></td>
-       </tr>
-       <tr>
-         <td>code<span class="since">(Since 1.2.12)</span></td>
-         <td>UINT8</td>
-         <td>ICMPv6 code end of range; requires <code>protocol</code> to be set to <code>icmpv6</code></td>
-       </tr>
-       <tr>
-         <td>comment <span class="since">(Since 0.8.5)</span></td>
-         <td>STRING</td>
-         <td>text with max. 256 characters</td>
-       </tr>
-      </table>
-    <p>
-      Valid strings for <code>protocol</code> are:
-         tcp, udp, udplite, esp, ah, icmpv6, sctp
-      <br/><br/>
-    </p>
-
-    <h5><a id="nwfelemsRulesProtoTCP-ipv4">TCP/UDP/SCTP</a></h5>
-    <p>
-      Protocol ID: <code>tcp</code>, <code>udp</code>, <code>sctp</code>
-      <br/>
-      Note: The chain parameter is ignored for this type of traffic
-      and should either be omitted or set to <code>root</code>.
-    </p>
-      <table class="top_table">
-       <tr>
-         <th> Attribute </th>
-         <th> Datatype </th>
-         <th> Semantics </th>
-       </tr>
-       <tr>
-         <td>srcmacaddr</td>
-         <td>MAC_ADDR</td>
-         <td>MAC address of sender</td>
-       </tr>
-       <tr>
-         <td>srcipaddr</td>
-         <td>IP_ADDR</td>
-         <td>Source IP address</td>
-       </tr>
-       <tr>
-         <td>srcipmask</td>
-         <td>IP_MASK</td>
-         <td>Mask applied to source IP address</td>
-       </tr>
-       <tr>
-         <td>dstipaddr</td>
-         <td>IP_ADDR</td>
-         <td>Destination IP address</td>
-       </tr>
-       <tr>
-         <td>dstipmask</td>
-         <td>IP_MASK</td>
-         <td>Mask applied to destination IP address</td>
-       </tr>
-
-       <tr>
-         <td>srcipfrom</td>
-         <td>IP_ADDR</td>
-         <td>Start of range of source IP address</td>
-       </tr>
-       <tr>
-         <td>srcipto</td>
-         <td>IP_ADDR</td>
-         <td>End of range of source IP address</td>
-       </tr>
-       <tr>
-         <td>dstipfrom</td>
-         <td>IP_ADDR</td>
-         <td>Start of range of destination IP address</td>
-       </tr>
-       <tr>
-         <td>dstipto</td>
-         <td>IP_ADDR</td>
-         <td>End of range of destination IP address</td>
-       </tr>
-
-       <tr>
-         <td>srcportstart</td>
-         <td>UINT16</td>
-         <td>Start of range of valid source ports</td>
-       </tr>
-       <tr>
-         <td>srcportend</td>
-         <td>UINT16</td>
-         <td>End of range of valid source ports</td>
-       </tr>
-       <tr>
-         <td>dstportstart</td>
-         <td>UINT16</td>
-         <td>Start of range of valid destination ports</td>
-       </tr>
-       <tr>
-         <td>dstportend</td>
-         <td>UINT16</td>
-         <td>End of range of valid destination ports</td>
-       </tr>
-       <tr>
-         <td>dscp</td>
-         <td>UINT8 (0x0-0x3f, 0 - 63)</td>
-         <td>Differentiated Services Code Point</td>
-       </tr>
-       <tr>
-         <td>comment <span class="since">(Since 0.8.5)</span></td>
-         <td>STRING</td>
-         <td>text with max. 256 characters</td>
-       </tr>
-       <tr>
-         <td>state <span class="since">(Since 0.8.5)</span></td>
-         <td>STRING</td>
-         <td>comma separated list of NEW,ESTABLISHED,RELATED,INVALID or NONE</td>
-       </tr>
-       <tr>
-         <td>flags <span class="since">(Since 0.9.1)</span></td>
-         <td>STRING</td>
-         <td>TCP-only: format of mask/flags with mask and flags each being a comma separated list of SYN,ACK,URG,PSH,FIN,RST or NONE or ALL</td>
-       </tr>
-       <tr>
-         <td>ipset <span class="since">(Since 0.9.13)</span></td>
-         <td>STRING</td>
-         <td>The name of an IPSet managed outside of libvirt</td>
-       </tr>
-       <tr>
-         <td>ipsetflags <span class="since">(Since 0.9.13)</span></td>
-         <td>IPSETFLAGS</td>
-         <td>flags for the IPSet; requires ipset attribute</td>
-       </tr>
-      </table>
-    <p>
-      <br/><br/>
-    </p>
-
-
-    <h5><a id="nwfelemsRulesProtoICMP">ICMP</a></h5>
-    <p>
-      Protocol ID: <code>icmp</code>
-      <br/>
-      Note: The chain parameter is ignored for this type of traffic
-      and should either be omitted or set to <code>root</code>.
-    </p>
-      <table class="top_table">
-       <tr>
-         <th> Attribute </th>
-         <th> Datatype </th>
-         <th> Semantics </th>
-       </tr>
-       <tr>
-         <td>srcmacaddr</td>
-         <td>MAC_ADDR</td>
-         <td>MAC address of sender</td>
-       </tr>
-       <tr>
-         <td>srcmacmask</td>
-         <td>MAC_MASK</td>
-         <td>Mask applied to MAC address of sender</td>
-       </tr>
-       <tr>
-         <td>dstmacaddr</td>
-         <td>MAC_ADDR</td>
-         <td>MAC address of destination</td>
-       </tr>
-       <tr>
-         <td>dstmacmask</td>
-         <td>MAC_MASK</td>
-         <td>Mask applied to MAC address of destination</td>
-       </tr>
-       <tr>
-         <td>srcipaddr</td>
-         <td>IP_ADDR</td>
-         <td>Source IP address</td>
-       </tr>
-       <tr>
-         <td>srcipmask</td>
-         <td>IP_MASK</td>
-         <td>Mask applied to source IP address</td>
-       </tr>
-       <tr>
-         <td>dstipaddr</td>
-         <td>IP_ADDR</td>
-         <td>Destination IP address</td>
-       </tr>
-       <tr>
-         <td>dstipmask</td>
-         <td>IP_MASK</td>
-         <td>Mask applied to destination IP address</td>
-       </tr>
-
-       <tr>
-         <td>srcipfrom</td>
-         <td>IP_ADDR</td>
-         <td>Start of range of source IP address</td>
-       </tr>
-       <tr>
-         <td>srcipto</td>
-         <td>IP_ADDR</td>
-         <td>End of range of source IP address</td>
-       </tr>
-       <tr>
-         <td>dstipfrom</td>
-         <td>IP_ADDR</td>
-         <td>Start of range of destination IP address</td>
-       </tr>
-       <tr>
-         <td>dstipto</td>
-         <td>IP_ADDR</td>
-         <td>End of range of destination IP address</td>
-       </tr>
-       <tr>
-         <td>type</td>
-         <td>UINT16</td>
-         <td>ICMP type</td>
-       </tr>
-       <tr>
-         <td>code</td>
-         <td>UINT16</td>
-         <td>ICMP code</td>
-       </tr>
-       <tr>
-         <td>dscp</td>
-         <td>UINT8 (0x0-0x3f, 0 - 63)</td>
-         <td>Differentiated Services Code Point</td>
-       </tr>
-       <tr>
-         <td>comment <span class="since">(Since 0.8.5)</span></td>
-         <td>STRING</td>
-         <td>text with max. 256 characters</td>
-       </tr>
-       <tr>
-         <td>state <span class="since">(Since 0.8.5)</span></td>
-         <td>STRING</td>
-         <td>comma separated list of NEW,ESTABLISHED,RELATED,INVALID or NONE</td>
-       </tr>
-       <tr>
-         <td>ipset <span class="since">(Since 0.9.13)</span></td>
-         <td>STRING</td>
-         <td>The name of an IPSet managed outside of libvirt</td>
-       </tr>
-       <tr>
-         <td>ipsetflags <span class="since">(Since 0.9.13)</span></td>
-         <td>IPSETFLAGS</td>
-         <td>flags for the IPSet; requires ipset attribute</td>
-       </tr>
-      </table>
-    <p>
-      <br/><br/>
-    </p>
-
-    <h5><a id="nwfelemsRulesProtoMisc">IGMP, ESP, AH, UDPLITE, 'ALL'</a></h5>
-    <p>
-      Protocol ID: <code>igmp</code>, <code>esp</code>, <code>ah</code>, <code>udplite</code>, <code>all</code>
-      <br/>
-      Note: The chain parameter is ignored for this type of traffic
-      and should either be omitted or set to <code>root</code>.
-    </p>
-      <table class="top_table">
-       <tr>
-         <th> Attribute </th>
-         <th> Datatype </th>
-         <th> Semantics </th>
-       </tr>
-       <tr>
-         <td>srcmacaddr</td>
-         <td>MAC_ADDR</td>
-         <td>MAC address of sender</td>
-       </tr>
-       <tr>
-         <td>srcmacmask</td>
-         <td>MAC_MASK</td>
-         <td>Mask applied to MAC address of sender</td>
-       </tr>
-       <tr>
-         <td>dstmacaddr</td>
-         <td>MAC_ADDR</td>
-         <td>MAC address of destination</td>
-       </tr>
-       <tr>
-         <td>dstmacmask</td>
-         <td>MAC_MASK</td>
-         <td>Mask applied to MAC address of destination</td>
-       </tr>
-       <tr>
-         <td>srcipaddr</td>
-         <td>IP_ADDR</td>
-         <td>Source IP address</td>
-       </tr>
-       <tr>
-         <td>srcipmask</td>
-         <td>IP_MASK</td>
-         <td>Mask applied to source IP address</td>
-       </tr>
-       <tr>
-         <td>dstipaddr</td>
-         <td>IP_ADDR</td>
-         <td>Destination IP address</td>
-       </tr>
-       <tr>
-         <td>dstipmask</td>
-         <td>IP_MASK</td>
-         <td>Mask applied to destination IP address</td>
-       </tr>
-
-       <tr>
-         <td>srcipfrom</td>
-         <td>IP_ADDR</td>
-         <td>Start of range of source IP address</td>
-       </tr>
-       <tr>
-         <td>srcipto</td>
-         <td>IP_ADDR</td>
-         <td>End of range of source IP address</td>
-       </tr>
-       <tr>
-         <td>dstipfrom</td>
-         <td>IP_ADDR</td>
-         <td>Start of range of destination IP address</td>
-       </tr>
-       <tr>
-         <td>dstipto</td>
-         <td>IP_ADDR</td>
-         <td>End of range of destination IP address</td>
-       </tr>
-       <tr>
-         <td>dscp</td>
-         <td>UINT8 (0x0-0x3f, 0 - 63)</td>
-         <td>Differentiated Services Code Point</td>
-       </tr>
-       <tr>
-         <td>comment <span class="since">(Since 0.8.5)</span></td>
-         <td>STRING</td>
-         <td>text with max. 256 characters</td>
-       </tr>
-       <tr>
-         <td>state <span class="since">(Since 0.8.5)</span></td>
-         <td>STRING</td>
-         <td>comma separated list of NEW,ESTABLISHED,RELATED,INVALID or NONE</td>
-       </tr>
-       <tr>
-         <td>ipset <span class="since">(Since 0.9.13)</span></td>
-         <td>STRING</td>
-         <td>The name of an IPSet managed outside of libvirt</td>
-       </tr>
-       <tr>
-         <td>ipsetflags <span class="since">(Since 0.9.13)</span></td>
-         <td>IPSETFLAGS</td>
-         <td>flags for the IPSet; requires ipset attribute</td>
-       </tr>
-      </table>
-    <p>
-      <br/><br/>
-    </p>
-
-
-    <h5><a id="nwfelemsRulesProtoTCP-ipv6">TCP/UDP/SCTP over IPV6</a></h5>
-    <p>
-      Protocol ID: <code>tcp-ipv6</code>, <code>udp-ipv6</code>, <code>sctp-ipv6</code>
-      <br/>
-      Note: The chain parameter is ignored for this type of traffic
-      and should either be omitted or set to <code>root</code>.
-    </p>
-      <table class="top_table">
-       <tr>
-         <th> Attribute </th>
-         <th> Datatype </th>
-         <th> Semantics </th>
-       </tr>
-       <tr>
-         <td>srcmacaddr</td>
-         <td>MAC_ADDR</td>
-         <td>MAC address of sender</td>
-       </tr>
-       <tr>
-         <td>srcipaddr</td>
-         <td>IPV6_ADDR</td>
-         <td>Source IP address</td>
-       </tr>
-       <tr>
-         <td>srcipmask</td>
-         <td>IPV6_MASK</td>
-         <td>Mask applied to source IP address</td>
-       </tr>
-       <tr>
-         <td>dstipaddr</td>
-         <td>IPV6_ADDR</td>
-         <td>Destination IP address</td>
-       </tr>
-       <tr>
-         <td>dstipmask</td>
-         <td>IPV6_MASK</td>
-         <td>Mask applied to destination IP address</td>
-       </tr>
-
-       <tr>
-         <td>srcipfrom</td>
-         <td>IPV6_ADDR</td>
-         <td>Start of range of source IP address</td>
-       </tr>
-       <tr>
-         <td>srcipto</td>
-         <td>IPV6_ADDR</td>
-         <td>End of range of source IP address</td>
-       </tr>
-       <tr>
-         <td>dstipfrom</td>
-         <td>IPV6_ADDR</td>
-         <td>Start of range of destination IP address</td>
-       </tr>
-       <tr>
-         <td>dstipto</td>
-         <td>IPV6_ADDR</td>
-         <td>End of range of destination IP address</td>
-       </tr>
-
-       <tr>
-         <td>srcportstart</td>
-         <td>UINT16</td>
-         <td>Start of range of valid source ports</td>
-       </tr>
-       <tr>
-         <td>srcportend</td>
-         <td>UINT16</td>
-         <td>End of range of valid source ports</td>
-       </tr>
-       <tr>
-         <td>dstportstart</td>
-         <td>UINT16</td>
-         <td>Start of range of valid destination ports</td>
-       </tr>
-       <tr>
-         <td>dstportend</td>
-         <td>UINT16</td>
-         <td>End of range of valid destination ports</td>
-       </tr>
-       <tr>
-         <td>dscp</td>
-         <td>UINT8 (0x0-0x3f, 0 - 63)</td>
-         <td>Differentiated Services Code Point</td>
-       </tr>
-       <tr>
-         <td>comment <span class="since">(Since 0.8.5)</span></td>
-         <td>STRING</td>
-         <td>text with max. 256 characters</td>
-       </tr>
-       <tr>
-         <td>state <span class="since">(Since 0.8.5)</span></td>
-         <td>STRING</td>
-         <td>comma separated list of NEW,ESTABLISHED,RELATED,INVALID or NONE</td>
-       </tr>
-       <tr>
-         <td>flags <span class="since">(Since 0.9.1)</span></td>
-         <td>STRING</td>
-         <td>TCP-only: format of mask/flags with mask and flags each being a comma separated list of SYN,ACK,URG,PSH,FIN,RST or NONE or ALL</td>
-       </tr>
-       <tr>
-         <td>ipset <span class="since">(Since 0.9.13)</span></td>
-         <td>STRING</td>
-         <td>The name of an IPSet managed outside of libvirt</td>
-       </tr>
-       <tr>
-         <td>ipsetflags <span class="since">(Since 0.9.13)</span></td>
-         <td>IPSETFLAGS</td>
-         <td>flags for the IPSet; requires ipset attribute</td>
-       </tr>
-      </table>
-    <p>
-      <br/><br/>
-    </p>
-
-
-    <h5><a id="nwfelemsRulesProtoICMPv6">ICMPv6</a></h5>
-    <p>
-      Protocol ID: <code>icmpv6</code>
-      <br/>
-      Note: The chain parameter is ignored for this type of traffic
-      and should either be omitted or set to <code>root</code>.
-    </p>
-      <table class="top_table">
-       <tr>
-         <th> Attribute </th>
-         <th> Datatype </th>
-         <th> Semantics </th>
-       </tr>
-       <tr>
-         <td>srcmacaddr</td>
-         <td>MAC_ADDR</td>
-         <td>MAC address of sender</td>
-       </tr>
-       <tr>
-         <td>srcipaddr</td>
-         <td>IPV6_ADDR</td>
-         <td>Source IPv6 address</td>
-       </tr>
-       <tr>
-         <td>srcipmask</td>
-         <td>IPV6_MASK</td>
-         <td>Mask applied to source IPv6 address</td>
-       </tr>
-       <tr>
-         <td>dstipaddr</td>
-         <td>IPV6_ADDR</td>
-         <td>Destination IPv6 address</td>
-       </tr>
-       <tr>
-         <td>dstipmask</td>
-         <td>IPV6_MASK</td>
-         <td>Mask applied to destination IPv6 address</td>
-       </tr>
-
-       <tr>
-         <td>srcipfrom</td>
-         <td>IPV6_ADDR</td>
-         <td>Start of range of source IP address</td>
-       </tr>
-       <tr>
-         <td>srcipto</td>
-         <td>IPV6_ADDR</td>
-         <td>End of range of source IP address</td>
-       </tr>
-       <tr>
-         <td>dstipfrom</td>
-         <td>IPV6_ADDR</td>
-         <td>Start of range of destination IP address</td>
-       </tr>
-       <tr>
-         <td>dstipto</td>
-         <td>IPV6_ADDR</td>
-         <td>End of range of destination IP address</td>
-       </tr>
-
-       <tr>
-         <td>type</td>
-         <td>UINT16</td>
-         <td>ICMPv6 type</td>
-       </tr>
-       <tr>
-         <td>code</td>
-         <td>UINT16</td>
-         <td>ICMPv6 code</td>
-       </tr>
-       <tr>
-         <td>dscp</td>
-         <td>UINT8 (0x0-0x3f, 0 - 63)</td>
-         <td>Differentiated Services Code Point</td>
-       </tr>
-       <tr>
-         <td>comment <span class="since">(Since 0.8.5)</span></td>
-         <td>STRING</td>
-         <td>text with max. 256 characters</td>
-       </tr>
-       <tr>
-         <td>state <span class="since">(Since 0.8.5)</span></td>
-         <td>STRING</td>
-         <td>comma separated list of NEW,ESTABLISHED,RELATED,INVALID or NONE</td>
-       </tr>
-       <tr>
-         <td>ipset <span class="since">(Since 0.9.13)</span></td>
-         <td>STRING</td>
-         <td>The name of an IPSet managed outside of libvirt</td>
-       </tr>
-       <tr>
-         <td>ipsetflags <span class="since">(Since 0.9.13)</span></td>
-         <td>IPSETFLAGS</td>
-         <td>flags for the IPSet; requires ipset attribute</td>
-       </tr>
-      </table>
-    <p>
-      <br/><br/>
-    </p>
-
-    <h5><a id="nwfelemsRulesProtoMiscv6">ESP, AH, UDPLITE, 'ALL' over IPv6</a></h5>
-    <p>
-      Protocol ID: <code>esp-ipv6</code>, <code>ah-ipv6</code>, <code>udplite-ipv6</code>, <code>all-ipv6</code>
-      <br/>
-      Note: The chain parameter is ignored for this type of traffic
-      and should either be omitted or set to <code>root</code>.
-    </p>
-      <table class="top_table">
-       <tr>
-         <th> Attribute </th>
-         <th> Datatype </th>
-         <th> Semantics </th>
-       </tr>
-       <tr>
-         <td>srcmacaddr</td>
-         <td>MAC_ADDR</td>
-         <td>MAC address of sender</td>
-       </tr>
-       <tr>
-         <td>srcipaddr</td>
-         <td>IPV6_ADDR</td>
-         <td>Source IPv6 address</td>
-       </tr>
-       <tr>
-         <td>srcipmask</td>
-         <td>IPV6_MASK</td>
-         <td>Mask applied to source IPv6 address</td>
-       </tr>
-       <tr>
-         <td>dstipaddr</td>
-         <td>IPV6_ADDR</td>
-         <td>Destination IPv6 address</td>
-       </tr>
-       <tr>
-         <td>dstipmask</td>
-         <td>IPV6_MASK</td>
-         <td>Mask applied to destination IPv6 address</td>
-       </tr>
-
-       <tr>
-         <td>srcipfrom</td>
-         <td>IPV6_ADDR</td>
-         <td>Start of range of source IP address</td>
-       </tr>
-       <tr>
-         <td>srcipto</td>
-         <td>IPV6_ADDR</td>
-         <td>End of range of source IP address</td>
-       </tr>
-       <tr>
-         <td>dstipfrom</td>
-         <td>IPV6_ADDR</td>
-         <td>Start of range of destination IP address</td>
-       </tr>
-       <tr>
-         <td>dstipto</td>
-         <td>IPV6_ADDR</td>
-         <td>End of range of destination IP address</td>
-       </tr>
-       <tr>
-         <td>dscp</td>
-         <td>UINT8 (0x0-0x3f, 0 - 63)</td>
-         <td>Differentiated Services Code Point</td>
-       </tr>
-       <tr>
-         <td>comment <span class="since">(Since 0.8.5)</span></td>
-         <td>STRING</td>
-         <td>text with max. 256 characters</td>
-       </tr>
-       <tr>
-         <td>state <span class="since">(Since 0.8.5)</span></td>
-         <td>STRING</td>
-         <td>comma separated list of NEW,ESTABLISHED,RELATED,INVALID or NONE</td>
-       </tr>
-       <tr>
-         <td>ipset <span class="since">(Since 0.9.13)</span></td>
-         <td>STRING</td>
-         <td>The name of an IPSet managed outside of libvirt</td>
-       </tr>
-       <tr>
-         <td>ipsetflags <span class="since">(Since 0.9.13)</span></td>
-         <td>IPSETFLAGS</td>
-         <td>flags for the IPSet; requires ipset attribute</td>
-       </tr>
-      </table>
-    <p>
-      <br/><br/>
-    </p>
-
-    <h3><a id="nwfelemsRulesAdv">Advanced Filter Configuration Topics</a></h3>
-    <p>
-     The following sections discuss advanced filter configuration
-     topics.
-    </p>
-
-    <h4><a id="nwfelemsRulesAdvTracking">Connection tracking</a></h4>
-    <p>
-     The network filtering subsystem (on Linux) makes use of the connection
-     tracking support of iptables. This helps in enforcing the
-     directionality of network traffic (state match) as well as
-     counting and limiting the number of simultaneous connections towards
-     a VM. As an example, if a VM has TCP port 8080
-     open as a server, clients may connect to the VM on port 8080.
-     Connection tracking and enforcement of directionality then prevents
-     the VM from initiating a connection from
-     (TCP client) port 8080 to the host back to a remote host.
-     More importantly, tracking helps to prevent
-     remote attackers from establishing a connection back to a VM. For example,
-     if the user inside the VM established a connection to
-     port 80 on an attacker site, then the attacker will not be able to
-     initiate a connection from TCP port 80 back towards the VM.
-     By default the connection state match that enables connection tracking
-     and then enforcement of directionality of traffic is turned on. <br/>
-     The following shows an example XML fragment where this feature has been
-     turned off for incoming connections to TCP port 12345.
-    </p>
-<pre>
-[...]
-<rule direction='in' action='accept' statematch='false'>
-  <tcp dstportstart='12345'/>
-</rule>
-[...]
-</pre>
-    <p>
-     This now allows incoming traffic to TCP port 12345, but would also
-     enable the initiation from (client) TCP port 12345 within the VM,
-     which may or may not be desirable.
-    </p>
-
-    <h4><a id="nwfelemsRulesAdvLimiting">Limiting Number of Connections</a></h4>
-    <p>
-     To limit the number of connections a VM may establish, a rule must
-     be provided that sets a limit of connections for a given
-     type of traffic. If for example a VM
-     is supposed to be allowed to only ping one other IP address at a time
-     and is supposed to have only one active incoming ssh connection at a
-     time, the following XML fragment can be used to achieve this.
-    </p>
-<pre>
-[...]
-<rule action='drop' direction='in' priority='400'>
-  <tcp connlimit-above='1'/>
-</rule>
-<rule action='accept' direction='in' priority='500'>
-  <tcp dstportstart='22'/>
-</rule>
-<rule action='drop' direction='out' priority='400'>
-  <icmp connlimit-above='1'/>
-</rule>
-<rule action='accept' direction='out' priority='500'>
-  <icmp/>
-</rule>
-<rule action='accept' direction='out' priority='500'>
-  <udp dstportstart='53'/>
-</rule>
-<rule action='drop' direction='inout' priority='1000'>
-  <all/>
-</rule>
-[...]
-</pre>
-    <p>
-     Note that the rule for the limit has to logically appear
-     before the rule for accepting the traffic.<br/>
-     An additional rule for letting DNS traffic to port 22
-     go out the VM has been added to avoid ssh sessions not
-     getting established for reasons related to DNS lookup failures
-     by the ssh daemon. Leaving this rule out may otherwise lead to
-     fun-filled debugging joy (symptom: ssh client seems to hang
-     while trying to connect).
-     <br/><br/>
-     Lot of care must be taken with timeouts related
-     to tracking of traffic. An ICMP ping that
-     the user may have terminated inside the VM may have a long
-     timeout in the host's connection tracking system and therefore
-     not allow another ICMP ping to go through for a while. Therefore,
-     the timeouts have to be tuned in the host's sysfs, i.e.,
-    </p>
-
-<pre>
-echo 3 > /proc/sys/net/netfilter/nf_conntrack_icmp_timeout
-</pre>
-    <p>
-      sets the ICMP connection tracking timeout to 3 seconds. The
-      effect of this is that once one ping is terminated, another
-      one can start after 3 seconds.<br/>
-      Further, we want to point out that a client that for whatever
-      reason has not properly closed a TCP connection may cause a
-      connection to be held open for a longer period of time,
-      depending to what timeout the <code>TCP established</code> state
-      timeout has been set to on the host. Also, idle connections may time
-      out in the connection tracking system but can be reactivated once
-      packets are exchanged. However, a newly initiated connection may force
-      an idle connection into TCP backoff if the number of allowed connections
-      is set to a too low limit, the new connection is established
-      and hits (not exceeds) the limit of allowed connections and for
-      example a key is pressed on the old ssh session, which now has become
-      unresponsive due to its traffic being dropped.
-      Therefore, the limit of connections should be rather high so that
-      fluctuations in new TCP connections don't cause odd
-      traffic behavior in relation to idle connections.
-    </p>
-
-    <h2><a id="nwfcli">Command line tools</a></h2>
-    <p>
-      The libvirt command line tool <code>virsh</code> has been extended
-      with life-cycle support for network filters. All commands related
-      to the network filtering subsystem start with the prefix
-      <code>nwfilter</code>. The following commands are available:
-    </p>
-    <ul>
-     <li>nwfilter-list : list UUIDs and names of all network filters</li>
-     <li>nwfilter-define : define a new network filter or update an existing one</li>
-     <li>nwfilter-undefine : delete a network filter given its name; it must not be currently in use</li>
-     <li>nwfilter-dumpxml : display a network filter given its name</li>
-     <li>nwfilter-edit : edit a network filter given its name</li>
-    </ul>
-
-    <h2><a id="nwfexamples">Pre-existing network filters</a></h2>
-    <p>
-     The following is a list of example network filters that are
-     automatically installed with libvirt.</p>
-      <table class="top_table">
-       <tr>
-         <th> Name </th>
-         <th> Description </th>
-       </tr>
-       <tr>
-         <td> no-arp-spoofing </td>
-         <td> Prevent a VM from spoofing ARP traffic; this filter
-              only allows ARP request and reply messages and enforces
-              that those packets contain the MAC and IP addresses
-              of the VM.</td>
-      </tr>
-       <tr>
-         <td> allow-arp </td>
-         <td> Allow ARP traffic in both directions</td>
-      </tr>
-       <tr>
-         <td> allow-ipv4 </td>
-         <td> Allow IPv4 traffic in both directions</td>
-      </tr>
-       <tr>
-         <td> allow-ipv6 </td>
-         <td> Allow IPv6 traffic in both directions</td>
-      </tr>
-       <tr>
-         <td> allow-incoming-ipv4 </td>
-         <td> Allow incoming IPv4 traffic</td>
-      </tr>
-       <tr>
-         <td> allow-incoming-ipv6 </td>
-         <td> Allow incoming IPv6 traffic</td>
-      </tr>
-       <tr>
-         <td> allow-dhcp </td>
-         <td> Allow a VM to request an IP address via DHCP (from any
-              DHCP server)</td>
-      </tr>
-       <tr>
-         <td> allow-dhcpv6 </td>
-         <td> Similar to allow-dhcp, but for DHCPv6 </td>
-      </tr>
-       <tr>
-         <td> allow-dhcp-server </td>
-         <td> Allow a VM to request an IP address from a specified
-              DHCP server. The dotted decimal IP address of the DHCP
-              server must be provided in a reference to this filter.
-              The name of the variable must be <i>DHCPSERVER</i>.</td>
-      </tr>
-       <tr>
-         <td> allow-dhcpv6-server </td>
-         <td> Similar to allow-dhcp-server, but for DHCPv6 </td>
-      </tr>
-       <tr>
-         <td> no-ip-spoofing </td>
-         <td> Prevent a VM from sending of IPv4 packets with
-              a source IP address different from the one
-              in the packet. </td>
-      </tr>
-       <tr>
-         <td> no-ipv6-spoofing </td>
-         <td> Similar to no-ip-spoofing, but for IPv6 </td>
-      </tr>
-       <tr>
-         <td> no-ip-multicast </td>
-         <td> Prevent a VM from sending IP multicast packets. </td>
-      </tr>
-       <tr>
-         <td> no-ipv6-multicast </td>
-         <td> Similar to no-ip-multicast, but for IPv6 </td>
-      </tr>
-       <tr>
-         <td> clean-traffic </td>
-         <td> Prevent MAC, IP and ARP spoofing. This filter references
-              several other filters as building blocks. </td>
-      </tr>
-      </table>
-    <p>
-     Note that most of the above filters are only building blocks and
-     require a combination with other filters to provide useful network
-     traffic filtering.
-     The most useful one in the above list is the <i>clean-traffic</i>
-     filter. This filter itself can for example be combined with the
-     <i>no-ip-multicast</i>
-     filter to prevent virtual machines from sending IP multicast traffic
-     on top of the prevention of packet spoofing.
-    </p>
-
-    <h2><a id="nwfwrite">Writing your own filters</a></h2>
-
-    <p>
-     Since libvirt only provides a couple of example networking filters, you
-     may consider writing your own. When planning on doing so
-     there are a couple of things
-     you may need to know regarding the network filtering subsystem and how
-     it works internally. Certainly you also have to know and understand
-     the protocols very well that you want to be filtering on so that
-     no further traffic than what you want can pass and that in fact the
-     traffic you want to allow does pass.
-     <br/><br/>
-     The network filtering subsystem is currently only available on
-     Linux hosts and only works for QEMU and KVM type of virtual machines.
-     On Linux
-     it builds upon the support for <code>ebtables</code>, <code>iptables
-     </code> and <code>ip6tables</code> and makes use of their features.
-     From the above list of supported protocols the following ones are
-     implemented using <code>ebtables</code>:
-    </p>
-    <ul>
-     <li>mac</li>
-     <li>stp (spanning tree protocol)</li>
-     <li>vlan (802.1Q)</li>
-     <li>arp, rarp</li>
-     <li>ipv4</li>
-     <li>ipv6</li>
-    </ul>
-
-    <p>
-    All other protocols over IPv4 are supported using iptables, those over
-    IPv6 are implemented using ip6tables.
-    <br/><br/>
-    On a Linux host, all traffic filtering instantiated by libvirt's network
-    filter subsystem first passes through the filtering support implemented
-    by ebtables and only then through iptables or ip6tables filters. If
-    a filter tree has rules with the protocols <code>mac</code>,
-    <code>stp</code>, <code>vlan</code>
-    <code>arp</code>, <code>rarp</code>, <code>ipv4</code>,
-    or <code>ipv6</code> ebtables rules will automatically be instantiated.
-    <br/>
-    The role of the <code>chain</code> attribute in the network filter
-    XML is that internally a new user-defined ebtables table is created
-    that then for example receives all <code>arp</code> traffic coming
-    from or going to a virtual machine if the chain <code>arp</code>
-    has been specified. Further, a rule is generated in an interface's
-    <code>root</code> chain that directs all ipv4 traffic into the
-    user-defined chain. Therefore, all ARP traffic rules should then be
-    placed into filters specifying this chain. This type of branching
-    into user-defined tables is only supported with filtering on the ebtables
-    layer.
-    <br/>
-    <span class="since">Since 0.9.8</span> multiple chains for the same
-    protocol can be created. For this the name of the chain must have
-    a prefix of one of the previously enumerated protocols. To create an
-    additional chain for handling of ARP traffic, a chain with name
-    <code>arp-test</code> can be specified.
-    <br/>
-    As an example, it is
-    possible to filter on UDP traffic by source and destination ports using
-    the <code>ip</code> protocol filter and specifying attributes for the
-    protocol, source and destination IP addresses and ports of UDP packets
-    that are to be accepted. This allows
-    early filtering of UDP traffic with ebtables. However, once an IP or IPv6
-    packet, such as a UDP packet,
-    has passed the ebtables layer and there is at least one rule in a filter
-    tree that instantiates iptables or ip6tables rules, a rule to let
-    the UDP packet pass will also be necessary to be provided for those
-    filtering layers. This can be
-    achieved with a rule containing an appropriate <code>udp</code> or
-    <code>udp-ipv6</code> traffic filtering node.
-    </p>
-
-    <h3><a id="nwfwriteexample">Example custom filter</a></h3>
-    <p>
-     As an example we want to now build a filter that fulfills the following
-     list of requirements:
-    </p>
-    <ul>
-     <li>prevents a VM's interface from MAC, IP and ARP spoofing</li>
-     <li>opens only TCP ports 22 and 80 of a VM's interface</li>
-     <li>allows the VM to send ping traffic from an interface
-        but not let the VM be pinged on the interface</li>
-     <li>allows the VM to do DNS lookups (UDP towards port 53)</li>
-    </ul>
-    <p>
-     The requirement to prevent spoofing is fulfilled by the existing
-     <code>clean-traffic</code> network filter, thus we will reference this
-     filter from our custom filter.
-     <br/>
-     To enable traffic for TCP ports 22 and 80 we will add 2 rules to
-     enable this type of traffic. To allow the VM to send ping traffic
-     we will add a rule for ICMP traffic. For simplicity reasons
-     we allow general ICMP traffic to be initiated from the VM, not
-     just ICMP echo request and response messages. To then
-     disallow all other traffic to reach or be initiated by the
-     VM we will then need to add a rule that drops all other traffic.
-     Assuming our VM is called <i>test</i> and
-     the interface we want to associate our filter with is called <i>eth0</i>,
-     we name our filter <i>test-eth0</i>.
-     The result of these considerations is the following network filter XML:
-    </p>
-<pre>
-<filter name='test-eth0'>
-  <!-- reference the clean traffic filter to prevent
-       MAC, IP and ARP spoofing. By not providing
-       and IP address parameter, libvirt will detect the
-       IP address the VM is using. -->
-  <filterref filter='clean-traffic'/>
-
-  <!-- enable TCP ports 22 (ssh) and 80 (http) to be reachable -->
-  <rule action='accept' direction='in'>
-    <tcp dstportstart='22'/>
-  </rule>
-
-  <rule action='accept' direction='in'>
-    <tcp dstportstart='80'/>
-  </rule>
-
-  <!-- enable general ICMP traffic to be initiated by the VM;
-       this includes ping traffic -->
-  <rule action='accept' direction='out'>
-    <icmp/>
-  </rule>
-
-  <!-- enable outgoing DNS lookups using UDP -->
-  <rule action='accept' direction='out'>
-    <udp dstportstart='53'/>
-  </rule>
-
-  <!-- drop all other traffic -->
-  <rule action='drop' direction='inout'>
-    <all/>
-  </rule>
-
-</filter>
-</pre>
-    <p>
-     Note that none of the rules in the above XML contain the
-     IP address of the VM as either source or destination address, yet
-     the filtering of the traffic works correctly. The reason is that
-     the evaluation  of the rules internally happens on a
-     per-interface basis and the rules are evaluated based on the knowledge
-     about which (tap) interface has sent or will receive the packet rather
-     than what their source or destination IP address may be.
-     <br/><br/>
-     An XML fragment for a possible network interface description inside
-     the domain XML of the <code>test</code> VM could then look like this:
-    </p>
-<pre>
-[...]
-<interface type='bridge'>
-  <source bridge='mybridge'/>
-  <filterref filter='test-eth0'/>
-</interface>
-[...]
-</pre>
-
-    <p>
-     To more strictly control the ICMP traffic and enforce that only
-     ICMP echo requests can be sent from the VM
-     and only ICMP echo responses be received by the VM, the above
-     <code>ICMP</code> rule can be replaced with the following two rules:
-    </p>
-<pre>
-<!-- enable outgoing ICMP echo requests-->
-<rule action='accept' direction='out'>
-  <icmp type='8'/>
-</rule>
-
-<!-- enable incoming ICMP echo replies-->
-<rule action='accept' direction='in'>
-  <icmp type='0'/>
-</rule>
-</pre>
-
-    <h3><a id="nwfwriteexample2nd">Second example custom filter</a></h3>
-    <p>
-     In this example we now want to build a similar filter as in the
-     example above, but extend the list of requirements with an
-     ftp server located inside the VM. Further, we will be using features
-     that have been added in <span class="since">version 0.8.5</span>.
-     The requirements for this filter are:
-    </p>
-    <ul>
-     <li>prevents a VM's interface from MAC, IP and ARP spoofing</li>
-     <li>opens only TCP ports 22 and 80 of a VM's interface</li>
-     <li>allows the VM to send ping traffic from an interface
-        but not let the VM be pinged on the interface</li>
-     <li>allows the VM to do DNS lookups (UDP towards port 53)</li>
-     <li>enable an ftp server (in active mode) to be run inside the VM</li>
-    </ul>
-    <p>
-     The additional requirement of allowing an ftp server to be run inside
-     the VM maps into the requirement of allowing port 21 to be reachable
-     for ftp control traffic as well as enabling the VM to establish an
-     outgoing tcp connection originating from the VM's TCP port 20 back to
-     the ftp client (ftp active mode). There are several ways of how this
-     filter can be written and we present 2 solutions.
-     <br/><br/>
-     The 1st solution makes use of the <code>state</code> attribute of
-     the TCP protocol that gives us a hook into the connection tracking
-     framework of the Linux host. For the VM-initiated ftp data connection
-     (ftp active mode) we use the <code>RELATED</code> state that allows
-     us to detect that the VM-initiated ftp data connection is a consequence of
-     ( or 'has a relationship with' ) an existing ftp control connection,
-     thus we want to allow it to let packets
-     pass the firewall. The <code>RELATED</code> state, however, is only
-     valid for the very first packet of the outgoing TCP connection for the
-     ftp data path. Afterwards, the state to compare against is
-     <code>ESTABLISHED</code>, which then applies equally
-     to the incoming and outgoing direction. All this is related to the ftp
-     data traffic originating from TCP port 20 of the VM. This then leads to
-     the following solution
-     <span class="since">(since 0.8.5 (QEMU, KVM))</span>:
-    </p>
-<pre>
-<filter name='test-eth0'>
-  <!-- reference the clean traffic filter to prevent
-       MAC, IP and ARP spoofing. By not providing
-       and IP address parameter, libvirt will detect the
-       IP address the VM is using. -->
-  <filterref filter='clean-traffic'/>
-
-  <!-- enable TCP port 21 (ftp-control) to be reachable -->
-  <rule action='accept' direction='in'>
-    <tcp dstportstart='21'/>
-  </rule>
-
-  <!-- enable TCP port 20 for VM-initiated ftp data connection
-       related to an existing ftp control connection -->
-  <rule action='accept' direction='out'>
-    <tcp srcportstart='20' state='RELATED,ESTABLISHED'/>
-  </rule>
-
-  <!-- accept all packets from client on the ftp data connection -->
-  <rule action='accept' direction='in'>
-    <tcp dstportstart='20' state='ESTABLISHED'/>
-  </rule>
-
-  <!-- enable TCP ports 22 (ssh) and 80 (http) to be reachable -->
-  <rule action='accept' direction='in'>
-    <tcp dstportstart='22'/>
-  </rule>
-
-  <rule action='accept' direction='in'>
-    <tcp dstportstart='80'/>
-  </rule>
-
-  <!-- enable general ICMP traffic to be initiated by the VM;
-       this includes ping traffic -->
-  <rule action='accept' direction='out'>
-    <icmp/>
-  </rule>
-
-  <!-- enable outgoing DNS lookups using UDP -->
-  <rule action='accept' direction='out'>
-    <udp dstportstart='53'/>
-  </rule>
-
-  <!-- drop all other traffic -->
-  <rule action='drop' direction='inout'>
-    <all/>
-  </rule>
-
-</filter>
-</pre>
-    <p>
-     Before trying out a filter using the <code>RELATED</code> state,
-     you have to make sure that the appropriate connection tracking module
-     has been loaded into the host's kernel. Depending on the version of the
-     kernel, you must run either one of the following two commands before
-     the ftp connection with the VM is established.
-    </p>
-<pre>
-modprobe nf_conntrack_ftp   # where available  or
-
-modprobe ip_conntrack_ftp   # if above is not available
-</pre>
-    <p>
-     If other protocols than ftp are to be used in conjunction with the
-     <code>RELATED</code> state, their corresponding module must be loaded.
-     Modules exist at least for the protocols ftp, tftp, irc, sip,
-     sctp, and amanda.
-    </p>
-    <p>
-     The 2nd solution makes uses the state flags of connections more
-     than the previous solution did.
-     In this solution we take advantage of the fact that the
-     <code>NEW</code> state of a connection is valid when the very
-     first packet of a traffic flow is seen. Subsequently, if the very first
-     packet of a flow is accepted, the flow becomes a connection and enters
-     the <code>ESTABLISHED</code> state. This allows us to write a general
-     rule for allowing packets of <code>ESTABLISHED</code> connections to
-     reach the VM or be sent by the VM.
-     We write specific rules for the very first packets identified by the
-     <code>NEW</code> state and for which ports they are acceptable. All
-     packets for ports that are not explicitly accepted will be dropped and
-     therefore the connection will not go into the <code>ESTABLISHED</code>
-     state and any subsequent packets be dropped.
-    </p>
-
-<pre>
-<filter name='test-eth0'>
-  <!-- reference the clean traffic filter to prevent
-       MAC, IP and ARP spoofing. By not providing
-       and IP address parameter, libvirt will detect the
-       IP address the VM is using. -->
-  <filterref filter='clean-traffic'/>
-
-  <!-- let the packets of all previously accepted connections reach the VM -->
-  <rule action='accept' direction='in'>
-    <all state='ESTABLISHED'/>
-  </rule>
-
-  <!-- let the packets of all previously accepted and related connections be sent from the VM -->
-  <rule action='accept' direction='out'>
-    <all state='ESTABLISHED,RELATED'/>
-  </rule>
-
-  <!-- enable traffic towards port 21 (ftp), 22 (ssh) and 80 (http) -->
-  <rule action='accept' direction='in'>
-    <tcp dstportstart='21' dstportend='22' state='NEW'/>
-  </rule>
-
-  <rule action='accept' direction='in'>
-    <tcp dstportstart='80' state='NEW'/>
-  </rule>
-
-  <!-- enable general ICMP traffic to be initiated by the VM;
-       this includes ping traffic -->
-  <rule action='accept' direction='out'>
-    <icmp state='NEW'/>
-  </rule>
-
-  <!-- enable outgoing DNS lookups using UDP -->
-  <rule action='accept' direction='out'>
-    <udp dstportstart='53' state='NEW'/>
-  </rule>
-
-  <!-- drop all other traffic -->
-  <rule action='drop' direction='inout'>
-    <all/>
-  </rule>
-
-</filter>
-
-</pre>
-
-    <h2><a id="nwflimits">Limitations</a></h2>
-    <p>
-     The following sections list (current) limitations of the network
-     filtering subsystem.
-    </p>
-
-    <h3><a id="nwflimitsmigr">VM Migration</a></h3>
-     <p>
-      VM migration is only supported if the whole filter tree
-      that is referenced by a virtual machine's top level filter
-      is also available on the target host. The network filter
-      <i>clean-traffic</i>
-      for example should be available on all libvirt installations
-      of version 0.8.1 or later and thus enable migration of VMs that
-      for example reference this filter. All other
-      custom filters must be migrated using higher layer software. It is
-      outside the scope of libvirt to ensure that referenced filters
-      on the source system are equivalent to those on the target system
-      and vice versa.
-      <br/><br/>
-      Migration must occur between libvirt installations of version
-      0.8.1 or later in order not to lose the network traffic filters
-      associated with an interface.
-     </p>
-    <h3><a id="nwflimitsvlan">VLAN filtering on Linux</a></h3>
-     <p>
-      VLAN (802.1Q) packets, if sent by a virtual machine, cannot be filtered
-      with rules for protocol IDs <code>arp</code>, <code>rarp</code>,
-      <code>ipv4</code> and <code>ipv6</code> but only
-      with protocol IDs <code>mac</code> and <code>vlan</code>. Therefore,
-      the example filter <code>clean-traffic</code> will not work as expected.
-     </p>
-  </body>
-</html>
diff --git a/docs/formatnwfilter.rst b/docs/formatnwfilter.rst
new file mode 100644
index 0000000000..434da5b1fd
--- /dev/null
+++ b/docs/formatnwfilter.rst
@@ -0,0 +1,1789 @@
+.. role:: since
+
+===============
+Network Filters
+===============
+
+.. contents::
+
+This page provides an introduction to libvirt's network filters, their goals,
+concepts and XML format.
+
+Goals and background
+--------------------
+
+The goal of the network filtering XML is to enable administrators of a
+virtualized system to configure and enforce network traffic filtering rules on
+virtual machines and manage the parameters of network traffic that virtual
+machines are allowed to send or receive. The network traffic filtering rules are
+applied on the host when a virtual machine is started. Since the filtering rules
+cannot be circumvented from within the virtual machine, it makes them mandatory
+from the point of view of a virtual machine user.
+
+The network filter subsystem allows each virtual machine's network traffic
+filtering rules to be configured individually on a per interface basis. The
+rules are applied on the host when the virtual machine is started and can be
+modified while the virtual machine is running. The latter can be achieved by
+modifying the XML description of a network filter.
+
+Multiple virtual machines can make use of the same generic network filter. When
+such a filter is modified, the network traffic filtering rules of all running
+virtual machines that reference this filter are updated.
+
+Network filtering support is available :since:`since 0.8.1 (QEMU, KVM)`
+
+Concepts
+--------
+
+The network traffic filtering subsystem enables configuration of network traffic
+filtering rules on individual network interfaces that are configured for certain
+types of network configurations. Supported network types are
+
+-  ``network``
+
+-  ``ethernet`` -- must be used in bridging mode
+
+-  ``bridge``
+
+The interface XML is used to reference a top-level filter. In the following
+example, the interface description references the filter ``clean-traffic``.
+
+::
+
+   ...
+   <devices>
+     <interface type='bridge'>
+       <mac address='00:16:3e:5d:c7:9e'/>
+       <filterref filter='clean-traffic'/>
+     </interface>
+   </devices>
+   ...
+
+Network filters are written in XML and may either contain references to other
+filters, contain rules for traffic filtering, or hold a combination of both. The
+above referenced filter ``clean-traffic`` is a filter that only contains
+references to other filters and no actual filtering rules. Since references to
+other filters can be used, a *tree* of filters can be built. The
+``clean-traffic`` filter can be viewed using the command
+``virsh nwfilter-dumpxml clean-traffic``.
+
+As previously mentioned, a single network filter can be referenced by multiple
+virtual machines. Since interfaces will typically have individual parameters
+associated with their respective traffic filtering rules, the rules described in
+a filter XML can be parameterized with variables. In this case, the variable
+name is used in the filter XML and the name and value are provided at the place
+where the filter is referenced. In the following example, the interface
+description has been extended with the parameter ``IP`` and a dotted IP address
+as value.
+
+::
+
+   ...
+   <devices>
+     <interface type='bridge'>
+       <mac address='00:16:3e:5d:c7:9e'/>
+       <filterref filter='clean-traffic'>
+         <parameter name='IP' value='10.0.0.1'/>
+       </filterref>
+     </interface>
+   </devices>
+   ...
+
+In this particular example, the ``clean-traffic`` network traffic filter will be
+instantiated with the IP address parameter 10.0.0.1 and enforce that the traffic
+from this interface will always be using 10.0.0.1 as the source IP address,
+which is one of the purposes of this particular filter.
+
+Filtering chains
+~~~~~~~~~~~~~~~~
+
+Filtering rules are organized in filter chains. These chains can be thought of
+as having a tree structure with packet filtering rules as entries in individual
+chains (branches).
+
+Packets start their filter evaluation in the ``root`` chain and can then
+continue their evaluation in other chains, return from those chains back into
+the ``root`` chain or be dropped or accepted by a filtering rule in one of the
+traversed chains.
+
+Libvirt's network filtering system automatically creates individual ``root``
+chains for every virtual machine's network interface on which the user chooses
+to activate traffic filtering. The user may write filtering rules that are
+either directly instantiated in the ``root`` chain or may create
+protocol-specific filtering chains for efficient evaluation of protocol-specific
+rules. The following chains exist:
+
+-  root
+
+-  mac :since:`(since 0.9.8)`
+
+-  stp (spanning tree protocol) :since:`(since 0.9.8)`
+
+-  vlan (802.1Q) :since:`(since 0.9.8)`
+
+-  arp, rarp
+
+-  ipv4
+
+-  ipv6
+
+:since:`Since 0.9.8` multiple chains evaluating the ``mac``, ``stp``, ``vlan``,
+``arp``, ``rarp``, ``ipv4``, or ``ipv6`` protocol can be created using the
+protocol name only as a prefix in the chain's name. This for examples allows
+chains with names ``arp-xyz`` or ``arp-test`` to be specified and have ARP
+protocol packets evaluated in those chains.
+
+The following filter shows an example of filtering ARP traffic in the ``arp``
+chain.
+
+::
+
+   <filter name='no-arp-spoofing' chain='arp' priority='-500'>
+     <uuid>f88f1932-debf-4aa1-9fbe-f10d3aa4bc95</uuid>
+     <rule action='drop' direction='out' priority='300'>
+       <mac match='no' srcmacaddr='$MAC'/>
+     </rule>
+     <rule action='drop' direction='out' priority='350'>
+       <arp match='no' arpsrcmacaddr='$MAC'/>
+     </rule>
+     <rule action='drop' direction='out' priority='400'>
+       <arp match='no' arpsrcipaddr='$IP'/>
+     </rule>
+     <rule action='drop' direction='in' priority='450'>
+       <arp opcode='Reply'/>
+       <arp match='no' arpdstmacaddr='$MAC'/>
+     </rule>
+     <rule action='drop' direction='in' priority='500'>
+       <arp match='no' arpdstipaddr='$IP'/>
+     </rule>
+     <rule action='accept' direction='inout' priority='600'>
+       <arp opcode='Request'/>
+     </rule>
+     <rule action='accept' direction='inout' priority='650'>
+       <arp opcode='Reply'/>
+     </rule>
+     <rule action='drop' direction='inout' priority='1000'/>
+   </filter>
+
+The consequence of putting ARP-specific rules in the ``arp`` chain, rather than
+for example in the ``root`` chain, is that packets for any other protocol than
+ARP do not need to be evaluated by ARP protocol-specific rules. This improves
+the efficiency of the traffic filtering. However, one must then pay attention to
+only put filtering rules for the given protocol into the chain since any other
+rules will not be evaluated, i.e., an IPv4 rule will not be evaluated in the ARP
+chain since no IPv4 protocol packets will traverse the ARP chain.
+
+Filtering chain priorities
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+All chains are connected to the ``root`` chain. The order in which those chains
+are accessed is influenced by the priority of the chain. The following table
+shows the chains that can be assigned a priority and their default priorities.
+
+============== ================
+Chain (prefix) Default priority
+============== ================
+stp            -810
+mac            -800
+vlan           -750
+ipv4           -700
+ipv6           -600
+arp            -500
+rarp           -400
+============== ================
+
+A chain with a lower priority value is accessed before one with a higher value.
+
+:since:`Since 0.9.8` the above listed chains can be assigned custom priorities
+by writing a value in the range [-1000, 1000] into the priority (XML) attribute
+in the filter node. The above example filter shows the default priority of -500
+for ``arp`` chains.
+
+Usage of variables in filters
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Two variables names have so far been reserved for usage by the network traffic
+filtering subsystem: ``MAC`` and ``IP``.
+
+``MAC`` is the MAC address of the network interface. A filtering rule that
+references this variable will automatically be instantiated with the MAC address
+of the interface. This works without the user having to explicitly provide the
+MAC parameter. Even though it is possible to specify the MAC parameter similar
+to the IP parameter above, it is discouraged since libvirt knows what MAC
+address an interface will be using.
+
+The parameter ``IP`` represents the IP address that the operating system inside
+the virtual machine is expected to use on the given interface. The ``IP``
+parameter is special in so far as the libvirt daemon will try to determine the
+IP address (and thus the IP parameter's value) that is being used on an
+interface if the parameter is not explicitly provided but referenced. For
+current limitations on IP address detection, consult the section on
+`Limitations`_ on how to use this feature and what to expect when using it.
+
+The above-shown network filer ``no-arp-spoofing`` is an example of a network
+filter XML referencing the ``MAC`` and ``IP`` variables.
+
+Note that referenced variables are always prefixed with the $ (dollar) sign. The
+format of the value of a variable must be of the type expected by the filter
+attribute in the XML. In the above example, the ``IP`` parameter must hold a
+dotted IP address in decimal numbers format. Failure to provide the correct
+value type will result in the filter not being instantiatable and will prevent a
+virtual machine from starting or the interface from attaching when hotplugging
+is used. The types that are expected for each XML attribute are shown below.
+
+:since:`Since 0.9.8` variables can contain lists of elements, e.g., the variable
+``IP`` can contain multiple IP addresses that are valid on a particular
+interface. The notation for providing multiple elements for the IP variable is:
+
+::
+
+   ...
+   <devices>
+     <interface type='bridge'>
+       <mac address='00:16:3e:5d:c7:9e'/>
+       <filterref filter='clean-traffic'>
+         <parameter name='IP' value='10.0.0.1'/>
+         <parameter name='IP' value='10.0.0.2'/>
+         <parameter name='IP' value='10.0.0.3'/>
+       </filterref>
+     </interface>
+   </devices>
+   ...
+
+This then allows filters to enable multiple IP addresses per interface.
+Therefore, with the list of IP address shown above, the following rule will
+create 3 individual filtering rules, one for each IP address.
+
+::
+
+   ...
+   <rule action='accept' direction='in' priority='500'>
+     <tcp srpipaddr='$IP'/>
+   </rule>
+   ...
+
+:since:`Since 0.9.10` it is possible to access individual elements of a variable
+holding a list of elements. A filtering rule like the following accesses the 2nd
+element of the variable DSTPORTS.
+
+::
+
+   ...
+   <rule action='accept' direction='in' priority='500'>
+     <udp dstportstart='$DSTPORTS[1]'/>
+   </rule>
+   ...
+
+:since:`Since 0.9.10` it is possible to create filtering rules that instantiate
+all combinations of rules from different lists using the notation of
+``$VARIABLE[@<iterator ID>]``. The following rule allows a virtual machine to
+receive traffic on a set of ports, which are specified in DSTPORTS, from the set
+of source IP address specified in SRCIPADDRESSES. The rule generates all
+combinations of elements of the variable DSTPORT with those of SRCIPADDRESSES by
+using two independent iterators to access their elements.
+
+::
+
+   ...
+   <rule action='accept' direction='in' priority='500'>
+     <ip srcipaddr='$SRCIPADDRESSES[@1]' dstportstart='$DSTPORTS[@2]'/>
+   </rule>
+   ...
+
+In an example we assign concrete values to SRCIPADDRESSES and DSTPORTS
+
+::
+
+   SRCIPADDRESSES = [ 10.0.0.1, 11.1.2.3 ]
+   DSTPORTS = [ 80, 8080 ]
+
+Accessing the variables using $SRCIPADDRESSES[@1] and $DSTPORTS[@2] would then
+result in all combinations of addresses and ports being created:
+
+::
+
+   10.0.0.1, 80
+   10.0.0.1, 8080
+   11.1.2.3, 80
+   11.1.2.3, 8080
+
+Accessing the same variables using a single iterator, for example by using the
+notation $SRCIPADDRESSES[@1] and $DSTPORTS[@1], would result in parallel access
+to both lists and result in the following combinations:
+
+::
+
+   10.0.0.1, 80
+   11.1.2.3, 8080
+
+Further, the notation of $VARIABLE is short-hand for $VARIABLE[@0]. The former
+notation always assumes the iterator with Id '0'.
+
+Automatic IP address detection
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The detection of IP addresses used on a virtual machine's interface is
+automatically activated if the variable ``IP`` is referenced but no value has
+been assigned to it. :since:`Since 0.9.13` the variable ``CTRL_IP_LEARNING`` can
+be used to specify the IP address learning method to use. Valid values are
+``any``, ``dhcp``, or ``none``.
+
+The value ``any`` means that libvirt may use any packet to determine the address
+in use by a virtual machine, which is the default behavior if the variable
+``CTRL_IP_LEARNING`` is not set. This method will only detect a single IP
+address on an interface. Once a VM's IP address has been detected, its IP
+network traffic will be locked to that address, if for example IP address
+spoofing is prevented by one of its filters. In that case the user of the VM
+will not be able to change the IP address on the interface inside the VM, which
+would be considered IP address spoofing. When a VM is migrated to another host
+or resumed after a suspend operation, the first packet sent by the VM will again
+determine the IP address it can use on a particular interface.
+
+A value of ``dhcp`` specifies that libvirt should only honor DHCP
+server-assigned addresses with valid leases. This method supports the detection
+and usage of multiple IP address per interface. When a VM is resumed after a
+suspend operation, still valid IP address leases are applied to its filters.
+Otherwise the VM is expected to again use DHCP to obtain new IP addresses. The
+migration of a VM to another physical host requires that the VM again runs the
+DHCP protocol.
+
+Use of ``CTRL_IP_LEARNING=dhcp`` (DHCP snooping) provides additional
+anti-spoofing security, especially when combined with a filter allowing only
+trusted DHCP servers to assign addresses. To enable this, set the variable
+``DHCPSERVER`` to the IP address of a valid DHCP server and provide filters that
+use this variable to filter incoming DHCP responses.
+
+When DHCP snooping is enabled and the DHCP lease expires, the VM will no longer
+be able to use the IP address until it acquires a new, valid lease from a DHCP
+server. If the VM is migrated, it must get a new valid DHCP lease to use an IP
+address (e.g., by bringing the VM interface down and up again).
+
+Note that automatic DHCP detection listens to the DHCP traffic the VM exchanges
+with the DHCP server of the infrastructure. To avoid denial-of-service attacks
+on libvirt, the evaluation of those packets is rate-limited, meaning that a VM
+sending an excessive number of DHCP packets per second on an interface will not
+have all of those packets evaluated and thus filters may not get adapted. Normal
+DHCP client behavior is assumed to send a low number of DHCP packets per second.
+Further, it is important to setup appropriate filters on all VMs in the
+infrastructure to avoid them being able to send DHCP packets. Therefore VMs must
+either be prevented from sending UDP and TCP traffic from port 67 to port 68 or
+the ``DHCPSERVER`` variable should be used on all VMs to restrict DHCP server
+messages to only be allowed to originate from trusted DHCP servers. At the same
+time anti-spoofing prevention must be enabled on all VMs in the subnet.
+
+If ``CTRL_IP_LEARNING`` is set to ``none``, libvirt does not do IP address
+learning and referencing ``IP`` without assigning it an explicit value is an
+error.
+
+The following XML provides an example for the activation of IP address learning
+using the DHCP snooping method:
+
+::
+
+   <interface type='bridge'>
+     <source bridge='virbr0'/>
+     <filterref filter='clean-traffic'>
+       <parameter name='CTRL_IP_LEARNING' value='dhcp'/>
+     </filterref>
+   </interface>
+
+Reserved Variables
+~~~~~~~~~~~~~~~~~~
+
+The following table lists reserved variables in use by libvirt.
+
++------------------+----------------------------------------------------------+
+| Variable Name    | Semantics                                                |
++==================+==========================================================+
+| MAC              | The MAC address of the interface                         |
++------------------+----------------------------------------------------------+
+| IP               | The list of IP addresses in use by an interface          |
++------------------+----------------------------------------------------------+
+| IPV6             | The list of IPV6 addresses in use by an interface        |
++------------------+----------------------------------------------------------+
+| DHCPSERVER       | The list of IP addresses of trusted DHCP servers         |
++------------------+----------------------------------------------------------+
+| DHCPSERVERV6     | Not currently implemented: The list of IPv6 addresses of |
+|                  | trusted DHCP servers                                     |
++------------------+----------------------------------------------------------+
+| CTRL_IP_LEARNING | The choice of the IP address detection mode              |
++------------------+----------------------------------------------------------+
+
+Element and attribute overview
+------------------------------
+
+The root element required for all network filters is named ``filter`` with two
+possible attributes. The ``name`` attribute provides a unique name of the given
+filter. The ``chain`` attribute is optional but allows certain filters to be
+better organized for more efficient processing by the firewall subsystem of the
+underlying host. Currently the system only supports the chains
+``root,       ipv4, ipv6, arp and rarp``.
+
+References to other filters
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Any filter may hold references to other filters. Individual filters may be
+referenced multiple times in a filter tree but references between filters must
+not introduce loops (directed acyclic graph).
+
+The following shows the XML of the ``clean-traffic`` network filter referencing
+several other filters.
+
+::
+
+   <filter name='clean-traffic'>
+     <uuid>6ef53069-ba34-94a0-d33d-17751b9b8cb1</uuid>
+     <filterref filter='no-mac-spoofing'/>
+     <filterref filter='no-ip-spoofing'/>
+     <filterref filter='allow-incoming-ipv4'/>
+     <filterref filter='no-arp-spoofing'/>
+     <filterref filter='no-other-l2-traffic'/>
+     <filterref filter='qemu-announce-self'/>
+   </filter>
+
+To reference another filter, the XML node ``filterref`` needs to be provided
+inside a ``filter`` node. This node must have the attribute ``filter`` whose
+value contains the name of the filter to be referenced.
+
+New network filters can be defined at any time and may contain references to
+network filters that are not known to libvirt, yet. However, once a virtual
+machine is started or a network interface referencing a filter is to be
+hotplugged, all network filters in the filter tree must be available. Otherwise
+the virtual machine will not start or the network interface cannot be attached.
+
+Filter rules
+~~~~~~~~~~~~
+
+The following XML shows a simple example of a network traffic filter
+implementing a rule to drop traffic if the IP address (provided through the
+value of the variable IP) in an outgoing IP packet is not the expected one, thus
+preventing IP address spoofing by the VM.
+
+::
+
+   <filter name='no-ip-spoofing' chain='ipv4'>
+     <uuid>fce8ae33-e69e-83bf-262e-30786c1f8072</uuid>
+     <rule action='drop' direction='out' priority='500'>
+       <ip match='no' srcipaddr='$IP'/>
+     </rule>
+   </filter>
+
+A traffic filtering rule starts with the ``rule`` node. This node may contain up
+to three attributes
+
+-  action -- mandatory; must either be ``drop`` (matching the rule silently
+   discards the packet with no further analysis), ``reject`` (matching the rule
+   generates an ICMP reject message with no further analysis) :since:`(since
+   0.9.0)` , ``accept`` (matching the rule accepts the packet with no further
+   analysis), ``return`` (matching the rule passes this filter, but returns
+   control to the calling filter for further analysis) :since:`(since 0.9.7)` ,
+   or ``continue`` (matching the rule goes on to the next rule for further
+   analysis) :since:`(since 0.9.7)` .
+
+-  direction -- mandatory; must either be ``in``, ``out`` or ``inout`` if the
+   rule is for incoming, outgoing or incoming-and-outgoing traffic
+
+-  priority -- optional; the priority of the rule controls the order in which
+   the rule will be instantiated relative to other rules. Rules with lower value
+   will be instantiated before rules with higher values. Valid values are in the
+   range of 0 to 1000. :since:`Since 0.9.8` this has been extended to cover the
+   range of -1000 to 1000. If this attribute is not provided, priority 500 will
+   automatically be assigned.
+
+   Note that filtering rules in the ``root`` chain are sorted with filters
+   connected to the ``root`` chain following their priorities. This allows to
+   interleave filtering rules with access to filter chains. (See also section on
+   `Filtering chain priorities`_ .)
+
+-  statematch -- optional; possible values are '0' or 'false' to turn the
+   underlying connection state matching off; default is 'true'
+
+   Also read the section on `Advanced Filter Configuration Topics`_.
+
+The above example indicates that the traffic of type ``ip`` will be associated
+with the chain 'ipv4' and the rule will have priority 500. If for example
+another filter is referenced whose traffic of type ``ip`` is also associated
+with the chain 'ipv4' then that filter's rules will be ordered relative to the
+priority 500 of the shown rule.
+
+A rule may contain a single rule for filtering of traffic. The above example
+shows that traffic of type ``ip`` is to be filtered.
+
+Supported protocols
+^^^^^^^^^^^^^^^^^^^
+
+The following sections enumerate the list of protocols that are supported by the
+network filtering subsystem. The type of traffic a rule is supposed to filter on
+is provided in the ``rule`` node as a nested node. Depending on the traffic type
+a rule is filtering, the attributes are different. The above example showed the
+single attribute ``srcipaddr`` that is valid inside the ``ip`` traffic filtering
+node. The following sections show what attributes are valid and what type of
+data they are expecting. The following datatypes are available:
+
+-  UINT8 : 8 bit integer; range 0-255
+
+-  UINT16: 16 bit integer; range 0-65535
+
+-  MAC_ADDR: MAC address in dotted decimal format, i.e., 00:11:22:33:44:55
+
+-  MAC_MASK: MAC address mask in MAC address format, i.e., FF:FF:FF:FC:00:00
+
+-  IP_ADDR: IP address in dotted decimal format, i.e., 10.1.2.3
+
+-  IP_MASK: IP address mask in either dotted decimal format (255.255.248.0) or
+   CIDR mask (0-32)
+
+-  IPV6_ADDR: IPv6 address in numbers format, i.e., FFFF::1
+
+-  IPV6_MASK: IPv6 mask in numbers format (FFFF:FFFF:FC00::) or CIDR mask
+   (0-128)
+
+-  STRING: A string
+
+-  BOOLEAN: 'true', 'yes', '1' or 'false', 'no', '0'
+
+-  IPSETFLAGS: The source and destination flags of the ipset described by up to
+   6 'src' or 'dst' elements selecting features from either the source or
+   destination part of the packet header; example: src,src,dst. The number of
+   'selectors' to provide here depends on the type of ipset that is referenced.
+
+Every attribute except for those of type IP_MASK or IPV6_MASK can be negated
+using the ``match`` attribute with value ``no``. Multiple negated attributes may
+be grouped together. The following XML fragment shows such an example using
+abstract attributes.
+
+::
+
+   [...]
+   <rule action='drop' direction='in'>
+     <protocol match='no' attribute1='value1' attribute2='value2'/>
+     <protocol attribute3='value3'/>
+   </rule>
+   [...]
+
+Rules perform a logical AND evaluation on all values of the given protocol
+attributes. Thus, if a single attribute's value does not match the one given in
+the rule, the whole rule will be skipped during evaluation. Therefore, in the
+above example incoming traffic will only be dropped if the protocol property
+attribute1 does not match value1 AND the protocol property attribute2 does not
+match value2 AND the protocol property attribute3 matches value3.
+
+MAC (Ethernet)
+''''''''''''''
+
+Protocol ID: ``mac``
+
+Note: Rules of this type should go into the ``root`` chain.
+
++-------------------------+-------------------------+-------------------------+
+| Attribute               | Datatype                | Semantics               |
++=========================+=========================+=========================+
+| srcmacaddr              | MAC_ADDR                | MAC address of sender   |
++-------------------------+-------------------------+-------------------------+
+| srcmacmask              | MAC_MASK                | Mask applied to MAC     |
+|                         |                         | address of sender       |
++-------------------------+-------------------------+-------------------------+
+| dstmacaddr              | MAC_ADDR                | MAC address of          |
+|                         |                         | destination             |
++-------------------------+-------------------------+-------------------------+
+| dstmacmask              | MAC_MASK                | Mask applied to MAC     |
+|                         |                         | address of destination  |
++-------------------------+-------------------------+-------------------------+
+| protocolid              | UINT16 (0x600-0xffff),  | Layer 3 protocol ID     |
+|                         | STRING                  |                         |
++-------------------------+-------------------------+-------------------------+
+| comment :since:`(Since  | STRING                  | text with max. 256      |
+| 0.8.5)`                 |                         | characters              |
++-------------------------+-------------------------+-------------------------+
+
+Valid Strings for ``protocolid`` are: arp, rarp, ipv4, ipv6
+
+::
+
+   [...]
+   <mac match='no' srcmacaddr='$MAC'/>
+   [...]
+
+VLAN (802.1Q) :since:`(Since 0.9.8)`
+''''''''''''''''''''''''''''''''''''
+
+Protocol ID: ``vlan``
+
+Note: Rules of this type should go either into the ``root`` or ``vlan`` chain.
+
++----------------+-----------------------------+-----------------------------+
+| Attribute      | Datatype                    | Semantics                   |
++================+=============================+=============================+
+| srcmacaddr     | MAC_ADDR                    | MAC address of sender       |
++----------------+-----------------------------+-----------------------------+
+| srcmacmask     | MAC_MASK                    | Mask applied to MAC address |
+|                |                             | of sender                   |
++----------------+-----------------------------+-----------------------------+
+| dstmacaddr     | MAC_ADDR                    | MAC address of destination  |
++----------------+-----------------------------+-----------------------------+
+| dstmacmask     | MAC_MASK                    | Mask applied to MAC address |
+|                |                             | of destination              |
++----------------+-----------------------------+-----------------------------+
+| vlanid         | UINT16 (0x0-0xfff, 0 -      | VLAN ID                     |
+|                | 4095)                       |                             |
++----------------+-----------------------------+-----------------------------+
+| encap-protocol | UINT16 (0x03c-0xfff),       | Encapsulated layer 3        |
+|                | String                      | protocol ID                 |
++----------------+-----------------------------+-----------------------------+
+| comment        | STRING                      | text with max. 256          |
+|                |                             | characters                  |
++----------------+-----------------------------+-----------------------------+
+
+Valid Strings for ``encap-protocol`` are: arp, ipv4, ipv6
+
+STP (Spanning Tree Protocol) (Since 0.9.8)
+''''''''''''''''''''''''''''''''''''''''''
+
+Protocol ID: ``stp``
+
+Note: Rules of this type should go either into the ``root`` or ``stp`` chain.
+
+=================== =========== =====================================
+Attribute           Datatype    Semantics
+=================== =========== =====================================
+srcmacaddr          MAC_ADDR    MAC address of sender
+srcmacmask          MAC_MASK    Mask applied to MAC address of sender
+type                UINT8       Bridge Protocol Data Unit (BPDU) type
+flags               UINT8       BPDU flag
+root-priority       UINT16      Root priority (range start)
+root-priority-hi    UINT16      Root priority range end
+root-address        MAC_ADDRESS Root MAC address
+root-address-mask   MAC_MASK    Root MAC address mask
+root-cost           UINT32      Root path cost (range start)
+root-cost-hi        UINT32      Root path cost range end
+sender-priority     UINT16      Sender priority (range start)
+sender-priority-hi  UINT16      Sender priority range end
+sender-address      MAC_ADDRESS BPDU sender MAC address
+sender-address-mask MAC_MASK    BPDU sender MAC address mask
+port                UINT16      Port identifier (range start)
+port_hi             UINT16      Port identifier range end
+msg-age             UINT16      Message age timer (range start)
+msg-age-hi          UINT16      Message age timer range end
+max-age             UINT16      Maximum age timer (range start)
+max-age-hi          UINT16      Maximum age timer range end
+hello-time          UINT16      Hello time timer (range start)
+hello-time-hi       UINT16      Hello time timer range end
+forward-delay       UINT16      Forward delay (range start)
+forward-delay-hi    UINT16      Forward delay range end
+comment             STRING      text with max. 256 characters
+=================== =========== =====================================
+
+ARP/RARP
+''''''''
+
+Protocol ID: ``arp`` or ``rarp``
+
+Note: Rules of this type should either go into the ``root`` or ``arp/rarp``
+chain.
+
++-----------------------------+----------------+-----------------------------+
+| Attribute                   | Datatype       | Semantics                   |
++=============================+================+=============================+
+| srcmacaddr                  | MAC_ADDR       | MAC address of sender       |
++-----------------------------+----------------+-----------------------------+
+| srcmacmask                  | MAC_MASK       | Mask applied to MAC address |
+|                             |                | of sender                   |
++-----------------------------+----------------+-----------------------------+
+| dstmacaddr                  | MAC_ADDR       | MAC address of destination  |
++-----------------------------+----------------+-----------------------------+
+| dstmacmask                  | MAC_MASK       | Mask applied to MAC address |
+|                             |                | of destination              |
++-----------------------------+----------------+-----------------------------+
+| hwtype                      | UINT16         | Hardware type               |
++-----------------------------+----------------+-----------------------------+
+| protocoltype                | UINT16         | Protocol type               |
++-----------------------------+----------------+-----------------------------+
+| opcode                      | UINT16, STRING | Opcode                      |
++-----------------------------+----------------+-----------------------------+
+| arpsrcmacaddr               | MAC_ADDR       | Source MAC address in       |
+|                             |                | ARP/RARP packet             |
++-----------------------------+----------------+-----------------------------+
+| arpdstmacaddr               | MAC_ADDR       | Destination MAC address in  |
+|                             |                | ARP/RARP packet             |
++-----------------------------+----------------+-----------------------------+
+| arpsrcipaddr                | IP_ADDR        | Source IP address in        |
+|                             |                | ARP/RARP packet             |
++-----------------------------+----------------+-----------------------------+
+| arpsrcipmask :since:`(Since | IP_MASK        | Source IP mask              |
+| 1.2.3)`                     |                |                             |
++-----------------------------+----------------+-----------------------------+
+| arpdstipaddr                | IP_ADDR        | Destination IP address in   |
+|                             |                | ARP/RARP packet             |
++-----------------------------+----------------+-----------------------------+
+| arpdstipmask :since:`(Since | IP_MASK        | Destination IP mask         |
+| 1.2.3)`                     |                |                             |
++-----------------------------+----------------+-----------------------------+
+| comment :since:`(Since      | STRING         | text with max. 256          |
+| 0.8.5)`                     |                | characters                  |
++-----------------------------+----------------+-----------------------------+
+| gratuitous :since:`(Since   | BOOLEAN        | boolean indicating whether  |
+| 0.9.2)`                     |                | to check for gratuitous ARP |
+|                             |                | packet                      |
++-----------------------------+----------------+-----------------------------+
+
+Valid strings for the ``Opcode`` field are: Request, Reply, Request_Reverse,
+Reply_Reverse, DRARP_Request, DRARP_Reply, DRARP_Error, InARP_Request, ARP_NAK
+
+IPv4
+''''
+
+Protocol ID: ``ip``
+
+Note: Rules of this type should either go into the ``root`` or ``ipv4`` chain.
+
++-------------------------+-------------------------+-------------------------+
+| Attribute               | Datatype                | Semantics               |
++=========================+=========================+=========================+
+| srcmacaddr              | MAC_ADDR                | MAC address of sender   |
++-------------------------+-------------------------+-------------------------+
+| srcmacmask              | MAC_MASK                | Mask applied to MAC     |
+|                         |                         | address of sender       |
++-------------------------+-------------------------+-------------------------+
+| dstmacaddr              | MAC_ADDR                | MAC address of          |
+|                         |                         | destination             |
++-------------------------+-------------------------+-------------------------+
+| dstmacmask              | MAC_MASK                | Mask applied to MAC     |
+|                         |                         | address of destination  |
++-------------------------+-------------------------+-------------------------+
+| srcipaddr               | IP_ADDR                 | Source IP address       |
++-------------------------+-------------------------+-------------------------+
+| srcipmask               | IP_MASK                 | Mask applied to source  |
+|                         |                         | IP address              |
++-------------------------+-------------------------+-------------------------+
+| dstipaddr               | IP_ADDR                 | Destination IP address  |
++-------------------------+-------------------------+-------------------------+
+| dstipmask               | IP_MASK                 | Mask applied to         |
+|                         |                         | destination IP address  |
++-------------------------+-------------------------+-------------------------+
+| protocol                | UINT8, STRING           | Layer 4 protocol        |
+|                         |                         | identifier              |
++-------------------------+-------------------------+-------------------------+
+| srcportstart            | UINT16                  | Start of range of valid |
+|                         |                         | source ports; requires  |
+|                         |                         | ``protocol``            |
++-------------------------+-------------------------+-------------------------+
+| srcportend              | UINT16                  | End of range of valid   |
+|                         |                         | source ports; requires  |
+|                         |                         | ``protocol``            |
++-------------------------+-------------------------+-------------------------+
+| dstportstart            | UINT16                  | Start of range of valid |
+|                         |                         | destination ports;      |
+|                         |                         | requires ``protocol``   |
++-------------------------+-------------------------+-------------------------+
+| dstportend              | UINT16                  | End of range of valid   |
+|                         |                         | destination ports;      |
+|                         |                         | requires ``protocol``   |
++-------------------------+-------------------------+-------------------------+
+| dscp                    | UINT8 (0x0-0x3f, 0 -    | Differentiated Services |
+|                         | 63)                     | Code Point              |
++-------------------------+-------------------------+-------------------------+
+| comment :since:`(Since  | STRING                  | text with max. 256      |
+| 0.8.5)`                 |                         | characters              |
++-------------------------+-------------------------+-------------------------+
+
+Valid strings for ``protocol`` are: tcp, udp, udplite, esp, ah, icmp, igmp, sctp
+
+IPv6
+''''
+
+Protocol ID: ``ipv6``
+
+Note: Rules of this type should either go into the ``root`` or ``ipv6`` chain.
+
++--------------------------------+-----------+--------------------------------+
+| Attribute                      | Datatype  | Semantics                      |
++================================+===========+================================+
+| srcmacaddr                     | MAC_ADDR  | MAC address of sender          |
++--------------------------------+-----------+--------------------------------+
+| srcmacmask                     | MAC_MASK  | Mask applied to MAC address of |
+|                                |           | sender                         |
++--------------------------------+-----------+--------------------------------+
+| dstmacaddr                     | MAC_ADDR  | MAC address of destination     |
++--------------------------------+-----------+--------------------------------+
+| dstmacmask                     | MAC_MASK  | Mask applied to MAC address of |
+|                                |           | destination                    |
++--------------------------------+-----------+--------------------------------+
+| srcipaddr                      | IPV6_ADDR | Source IPv6 address            |
++--------------------------------+-----------+--------------------------------+
+| srcipmask                      | IPV6_MASK | Mask applied to source IPv6    |
+|                                |           | address                        |
++--------------------------------+-----------+--------------------------------+
+| dstipaddr                      | IPV6_ADDR | Destination IPv6 address       |
++--------------------------------+-----------+--------------------------------+
+| dstipmask                      | IPV6_MASK | Mask applied to destination    |
+|                                |           | IPv6 address                   |
++--------------------------------+-----------+--------------------------------+
+| protocol                       | UINT8     | Layer 4 protocol identifier    |
++--------------------------------+-----------+--------------------------------+
+| srcportstart                   | UINT16    | Start of range of valid source |
+|                                |           | ports; requires ``protocol``   |
++--------------------------------+-----------+--------------------------------+
+| srcportend                     | UINT16    | End of range of valid source   |
+|                                |           | ports; requires ``protocol``   |
++--------------------------------+-----------+--------------------------------+
+| dstportstart                   | UINT16    | Start of range of valid        |
+|                                |           | destination ports; requires    |
+|                                |           | ``protocol``                   |
++--------------------------------+-----------+--------------------------------+
+| dstportend                     | UINT16    | End of range of valid          |
+|                                |           | destination ports; requires    |
+|                                |           | ``protocol``                   |
++--------------------------------+-----------+--------------------------------+
+| type :since:`(Since 1.2.12)`   | UINT8     | ICMPv6 type; requires          |
+|                                |           | ``protocol`` to be set to      |
+|                                |           | ``icmpv6``                     |
++--------------------------------+-----------+--------------------------------+
+| typeend :since:`(Since         | UINT8     | ICMPv6 type end of range;      |
+| 1.2.12)`                       |           | requires ``protocol`` to be    |
+|                                |           | set to ``icmpv6``              |
++--------------------------------+-----------+--------------------------------+
+| code :since:`(Since 1.2.12)`   | UINT8     | ICMPv6 code; requires          |
+|                                |           | ``protocol`` to be set to      |
+|                                |           | ``icmpv6``                     |
++--------------------------------+-----------+--------------------------------+
+| code :since:`(Since 1.2.12)`   | UINT8     | ICMPv6 code end of range;      |
+|                                |           | requires ``protocol`` to be    |
+|                                |           | set to ``icmpv6``              |
++--------------------------------+-----------+--------------------------------+
+| comment :since:`(Since 0.8.5)` | STRING    | text with max. 256 characters  |
++--------------------------------+-----------+--------------------------------+
+
+Valid strings for ``protocol`` are: tcp, udp, udplite, esp, ah, icmpv6, sctp
+
+TCP/UDP/SCTP
+''''''''''''
+
+Protocol ID: ``tcp``, ``udp``, ``sctp``
+
+Note: The chain parameter is ignored for this type of traffic and should either
+be omitted or set to ``root``.
+
++-------------------------+-------------------------+-------------------------+
+| Attribute               | Datatype                | Semantics               |
++=========================+=========================+=========================+
+| srcmacaddr              | MAC_ADDR                | MAC address of sender   |
++-------------------------+-------------------------+-------------------------+
+| srcipaddr               | IP_ADDR                 | Source IP address       |
++-------------------------+-------------------------+-------------------------+
+| srcipmask               | IP_MASK                 | Mask applied to source  |
+|                         |                         | IP address              |
++-------------------------+-------------------------+-------------------------+
+| dstipaddr               | IP_ADDR                 | Destination IP address  |
++-------------------------+-------------------------+-------------------------+
+| dstipmask               | IP_MASK                 | Mask applied to         |
+|                         |                         | destination IP address  |
++-------------------------+-------------------------+-------------------------+
+| srcipfrom               | IP_ADDR                 | Start of range of       |
+|                         |                         | source IP address       |
++-------------------------+-------------------------+-------------------------+
+| srcipto                 | IP_ADDR                 | End of range of source  |
+|                         |                         | IP address              |
++-------------------------+-------------------------+-------------------------+
+| dstipfrom               | IP_ADDR                 | Start of range of       |
+|                         |                         | destination IP address  |
++-------------------------+-------------------------+-------------------------+
+| dstipto                 | IP_ADDR                 | End of range of         |
+|                         |                         | destination IP address  |
++-------------------------+-------------------------+-------------------------+
+| srcportstart            | UINT16                  | Start of range of valid |
+|                         |                         | source ports            |
++-------------------------+-------------------------+-------------------------+
+| srcportend              | UINT16                  | End of range of valid   |
+|                         |                         | source ports            |
++-------------------------+-------------------------+-------------------------+
+| dstportstart            | UINT16                  | Start of range of valid |
+|                         |                         | destination ports       |
++-------------------------+-------------------------+-------------------------+
+| dstportend              | UINT16                  | End of range of valid   |
+|                         |                         | destination ports       |
++-------------------------+-------------------------+-------------------------+
+| dscp                    | UINT8 (0x0-0x3f, 0 -    | Differentiated Services |
+|                         | 63)                     | Code Point              |
++-------------------------+-------------------------+-------------------------+
+| comment :since:`(Since  | STRING                  | text with max. 256      |
+| 0.8.5)`                 |                         | characters              |
++-------------------------+-------------------------+-------------------------+
+| state :since:`(Since    | STRING                  | comma separated list of |
+| 0.8.5)`                 |                         | NEW,ESTA                |
+|                         |                         | BLISHED,RELATED,INVALID |
+|                         |                         | or NONE                 |
++-------------------------+-------------------------+-------------------------+
+| flags :since:`(Since    | STRING                  | TCP-only: format of     |
+| 0.9.1)`                 |                         | mask/flags with mask    |
+|                         |                         | and flags each being a  |
+|                         |                         | comma separated list of |
+|                         |                         | SYN,ACK,URG,PSH,FIN,RST |
+|                         |                         | or NONE or ALL          |
++-------------------------+-------------------------+-------------------------+
+| ipset :since:`(Since    | STRING                  | The name of an IPSet    |
+| 0.9.13)`                |                         | managed outside of      |
+|                         |                         | libvirt                 |
++-------------------------+-------------------------+-------------------------+
+| ipsetflags              | IPSETFLAGS              | flags for the IPSet;    |
+| :since:`(Since 0.9.13)` |                         | requires ipset          |
+|                         |                         | attribute               |
++-------------------------+-------------------------+-------------------------+
+
+ICMP
+''''
+
+Protocol ID: ``icmp``
+
+Note: The chain parameter is ignored for this type of traffic and should either
+be omitted or set to ``root``.
+
++-------------------------+-------------------------+-------------------------+
+| Attribute               | Datatype                | Semantics               |
++=========================+=========================+=========================+
+| srcmacaddr              | MAC_ADDR                | MAC address of sender   |
++-------------------------+-------------------------+-------------------------+
+| srcmacmask              | MAC_MASK                | Mask applied to MAC     |
+|                         |                         | address of sender       |
++-------------------------+-------------------------+-------------------------+
+| dstmacaddr              | MAC_ADDR                | MAC address of          |
+|                         |                         | destination             |
++-------------------------+-------------------------+-------------------------+
+| dstmacmask              | MAC_MASK                | Mask applied to MAC     |
+|                         |                         | address of destination  |
++-------------------------+-------------------------+-------------------------+
+| srcipaddr               | IP_ADDR                 | Source IP address       |
++-------------------------+-------------------------+-------------------------+
+| srcipmask               | IP_MASK                 | Mask applied to source  |
+|                         |                         | IP address              |
++-------------------------+-------------------------+-------------------------+
+| dstipaddr               | IP_ADDR                 | Destination IP address  |
++-------------------------+-------------------------+-------------------------+
+| dstipmask               | IP_MASK                 | Mask applied to         |
+|                         |                         | destination IP address  |
++-------------------------+-------------------------+-------------------------+
+| srcipfrom               | IP_ADDR                 | Start of range of       |
+|                         |                         | source IP address       |
++-------------------------+-------------------------+-------------------------+
+| srcipto                 | IP_ADDR                 | End of range of source  |
+|                         |                         | IP address              |
++-------------------------+-------------------------+-------------------------+
+| dstipfrom               | IP_ADDR                 | Start of range of       |
+|                         |                         | destination IP address  |
++-------------------------+-------------------------+-------------------------+
+| dstipto                 | IP_ADDR                 | End of range of         |
+|                         |                         | destination IP address  |
++-------------------------+-------------------------+-------------------------+
+| type                    | UINT16                  | ICMP type               |
++-------------------------+-------------------------+-------------------------+
+| code                    | UINT16                  | ICMP code               |
++-------------------------+-------------------------+-------------------------+
+| dscp                    | UINT8 (0x0-0x3f, 0 -    | Differentiated Services |
+|                         | 63)                     | Code Point              |
++-------------------------+-------------------------+-------------------------+
+| comment :since:`(Since  | STRING                  | text with max. 256      |
+| 0.8.5)`                 |                         | characters              |
++-------------------------+-------------------------+-------------------------+
+| state :since:`(Since    | STRING                  | comma separated list of |
+| 0.8.5)`                 |                         | NEW,ESTA                |
+|                         |                         | BLISHED,RELATED,INVALID |
+|                         |                         | or NONE                 |
++-------------------------+-------------------------+-------------------------+
+| ipset :since:`(Since    | STRING                  | The name of an IPSet    |
+| 0.9.13)`                |                         | managed outside of      |
+|                         |                         | libvirt                 |
++-------------------------+-------------------------+-------------------------+
+| ipsetflags              | IPSETFLAGS              | flags for the IPSet;    |
+| :since:`(Since 0.9.13)` |                         | requires ipset          |
+|                         |                         | attribute               |
++-------------------------+-------------------------+-------------------------+
+
+IGMP, ESP, AH, UDPLITE, 'ALL'
+'''''''''''''''''''''''''''''
+
+Protocol ID: ``igmp``, ``esp``, ``ah``, ``udplite``, ``all``
+
+Note: The chain parameter is ignored for this type of traffic and should either
+be omitted or set to ``root``.
+
++-------------------------+-------------------------+-------------------------+
+| Attribute               | Datatype                | Semantics               |
++=========================+=========================+=========================+
+| srcmacaddr              | MAC_ADDR                | MAC address of sender   |
++-------------------------+-------------------------+-------------------------+
+| srcmacmask              | MAC_MASK                | Mask applied to MAC     |
+|                         |                         | address of sender       |
++-------------------------+-------------------------+-------------------------+
+| dstmacaddr              | MAC_ADDR                | MAC address of          |
+|                         |                         | destination             |
++-------------------------+-------------------------+-------------------------+
+| dstmacmask              | MAC_MASK                | Mask applied to MAC     |
+|                         |                         | address of destination  |
++-------------------------+-------------------------+-------------------------+
+| srcipaddr               | IP_ADDR                 | Source IP address       |
++-------------------------+-------------------------+-------------------------+
+| srcipmask               | IP_MASK                 | Mask applied to source  |
+|                         |                         | IP address              |
++-------------------------+-------------------------+-------------------------+
+| dstipaddr               | IP_ADDR                 | Destination IP address  |
++-------------------------+-------------------------+-------------------------+
+| dstipmask               | IP_MASK                 | Mask applied to         |
+|                         |                         | destination IP address  |
++-------------------------+-------------------------+-------------------------+
+| srcipfrom               | IP_ADDR                 | Start of range of       |
+|                         |                         | source IP address       |
++-------------------------+-------------------------+-------------------------+
+| srcipto                 | IP_ADDR                 | End of range of source  |
+|                         |                         | IP address              |
++-------------------------+-------------------------+-------------------------+
+| dstipfrom               | IP_ADDR                 | Start of range of       |
+|                         |                         | destination IP address  |
++-------------------------+-------------------------+-------------------------+
+| dstipto                 | IP_ADDR                 | End of range of         |
+|                         |                         | destination IP address  |
++-------------------------+-------------------------+-------------------------+
+| dscp                    | UINT8 (0x0-0x3f, 0 -    | Differentiated Services |
+|                         | 63)                     | Code Point              |
++-------------------------+-------------------------+-------------------------+
+| comment :since:`(Since  | STRING                  | text with max. 256      |
+| 0.8.5)`                 |                         | characters              |
++-------------------------+-------------------------+-------------------------+
+| state :since:`(Since    | STRING                  | comma separated list of |
+| 0.8.5)`                 |                         | NEW,ESTA                |
+|                         |                         | BLISHED,RELATED,INVALID |
+|                         |                         | or NONE                 |
++-------------------------+-------------------------+-------------------------+
+| ipset :since:`(Since    | STRING                  | The name of an IPSet    |
+| 0.9.13)`                |                         | managed outside of      |
+|                         |                         | libvirt                 |
++-------------------------+-------------------------+-------------------------+
+| ipsetflags              | IPSETFLAGS              | flags for the IPSet;    |
+| :since:`(Since 0.9.13)` |                         | requires ipset          |
+|                         |                         | attribute               |
++-------------------------+-------------------------+-------------------------+
+
+TCP/UDP/SCTP over IPV6
+''''''''''''''''''''''
+
+Protocol ID: ``tcp-ipv6``, ``udp-ipv6``, ``sctp-ipv6``
+
+Note: The chain parameter is ignored for this type of traffic and should either
+be omitted or set to ``root``.
+
++-------------------------+-------------------------+-------------------------+
+| Attribute               | Datatype                | Semantics               |
++=========================+=========================+=========================+
+| srcmacaddr              | MAC_ADDR                | MAC address of sender   |
++-------------------------+-------------------------+-------------------------+
+| srcipaddr               | IPV6_ADDR               | Source IP address       |
++-------------------------+-------------------------+-------------------------+
+| srcipmask               | IPV6_MASK               | Mask applied to source  |
+|                         |                         | IP address              |
++-------------------------+-------------------------+-------------------------+
+| dstipaddr               | IPV6_ADDR               | Destination IP address  |
++-------------------------+-------------------------+-------------------------+
+| dstipmask               | IPV6_MASK               | Mask applied to         |
+|                         |                         | destination IP address  |
++-------------------------+-------------------------+-------------------------+
+| srcipfrom               | IPV6_ADDR               | Start of range of       |
+|                         |                         | source IP address       |
++-------------------------+-------------------------+-------------------------+
+| srcipto                 | IPV6_ADDR               | End of range of source  |
+|                         |                         | IP address              |
++-------------------------+-------------------------+-------------------------+
+| dstipfrom               | IPV6_ADDR               | Start of range of       |
+|                         |                         | destination IP address  |
++-------------------------+-------------------------+-------------------------+
+| dstipto                 | IPV6_ADDR               | End of range of         |
+|                         |                         | destination IP address  |
++-------------------------+-------------------------+-------------------------+
+| srcportstart            | UINT16                  | Start of range of valid |
+|                         |                         | source ports            |
++-------------------------+-------------------------+-------------------------+
+| srcportend              | UINT16                  | End of range of valid   |
+|                         |                         | source ports            |
++-------------------------+-------------------------+-------------------------+
+| dstportstart            | UINT16                  | Start of range of valid |
+|                         |                         | destination ports       |
++-------------------------+-------------------------+-------------------------+
+| dstportend              | UINT16                  | End of range of valid   |
+|                         |                         | destination ports       |
++-------------------------+-------------------------+-------------------------+
+| dscp                    | UINT8 (0x0-0x3f, 0 -    | Differentiated Services |
+|                         | 63)                     | Code Point              |
++-------------------------+-------------------------+-------------------------+
+| comment :since:`(Since  | STRING                  | text with max. 256      |
+| 0.8.5)`                 |                         | characters              |
++-------------------------+-------------------------+-------------------------+
+| state :since:`(Since    | STRING                  | comma separated list of |
+| 0.8.5)`                 |                         | NEW,ESTA                |
+|                         |                         | BLISHED,RELATED,INVALID |
+|                         |                         | or NONE                 |
++-------------------------+-------------------------+-------------------------+
+| flags :since:`(Since    | STRING                  | TCP-only: format of     |
+| 0.9.1)`                 |                         | mask/flags with mask    |
+|                         |                         | and flags each being a  |
+|                         |                         | comma separated list of |
+|                         |                         | SYN,ACK,URG,PSH,FIN,RST |
+|                         |                         | or NONE or ALL          |
++-------------------------+-------------------------+-------------------------+
+| ipset :since:`(Since    | STRING                  | The name of an IPSet    |
+| 0.9.13)`                |                         | managed outside of      |
+|                         |                         | libvirt                 |
++-------------------------+-------------------------+-------------------------+
+| ipsetflags              | IPSETFLAGS              | flags for the IPSet;    |
+| :since:`(Since 0.9.13)` |                         | requires ipset          |
+|                         |                         | attribute               |
++-------------------------+-------------------------+-------------------------+
+
+ICMPv6
+''''''
+
+Protocol ID: ``icmpv6``
+
+Note: The chain parameter is ignored for this type of traffic and should either
+be omitted or set to ``root``.
+
++-------------------------+-------------------------+-------------------------+
+| Attribute               | Datatype                | Semantics               |
++=========================+=========================+=========================+
+| srcmacaddr              | MAC_ADDR                | MAC address of sender   |
++-------------------------+-------------------------+-------------------------+
+| srcipaddr               | IPV6_ADDR               | Source IPv6 address     |
++-------------------------+-------------------------+-------------------------+
+| srcipmask               | IPV6_MASK               | Mask applied to source  |
+|                         |                         | IPv6 address            |
++-------------------------+-------------------------+-------------------------+
+| dstipaddr               | IPV6_ADDR               | Destination IPv6        |
+|                         |                         | address                 |
++-------------------------+-------------------------+-------------------------+
+| dstipmask               | IPV6_MASK               | Mask applied to         |
+|                         |                         | destination IPv6        |
+|                         |                         | address                 |
++-------------------------+-------------------------+-------------------------+
+| srcipfrom               | IPV6_ADDR               | Start of range of       |
+|                         |                         | source IP address       |
++-------------------------+-------------------------+-------------------------+
+| srcipto                 | IPV6_ADDR               | End of range of source  |
+|                         |                         | IP address              |
++-------------------------+-------------------------+-------------------------+
+| dstipfrom               | IPV6_ADDR               | Start of range of       |
+|                         |                         | destination IP address  |
++-------------------------+-------------------------+-------------------------+
+| dstipto                 | IPV6_ADDR               | End of range of         |
+|                         |                         | destination IP address  |
++-------------------------+-------------------------+-------------------------+
+| type                    | UINT16                  | ICMPv6 type             |
++-------------------------+-------------------------+-------------------------+
+| code                    | UINT16                  | ICMPv6 code             |
++-------------------------+-------------------------+-------------------------+
+| dscp                    | UINT8 (0x0-0x3f, 0 -    | Differentiated Services |
+|                         | 63)                     | Code Point              |
++-------------------------+-------------------------+-------------------------+
+| comment :since:`(Since  | STRING                  | text with max. 256      |
+| 0.8.5)`                 |                         | characters              |
++-------------------------+-------------------------+-------------------------+
+| state :since:`(Since    | STRING                  | comma separated list of |
+| 0.8.5)`                 |                         | NEW,ESTA                |
+|                         |                         | BLISHED,RELATED,INVALID |
+|                         |                         | or NONE                 |
++-------------------------+-------------------------+-------------------------+
+| ipset :since:`(Since    | STRING                  | The name of an IPSet    |
+| 0.9.13)`                |                         | managed outside of      |
+|                         |                         | libvirt                 |
++-------------------------+-------------------------+-------------------------+
+| ipsetflags              | IPSETFLAGS              | flags for the IPSet;    |
+| :since:`(Since 0.9.13)` |                         | requires ipset          |
+|                         |                         | attribute               |
++-------------------------+-------------------------+-------------------------+
+
+ESP, AH, UDPLITE, 'ALL' over IPv6
+'''''''''''''''''''''''''''''''''
+
+Protocol ID: ``esp-ipv6``, ``ah-ipv6``, ``udplite-ipv6``, ``all-ipv6``
+
+Note: The chain parameter is ignored for this type of traffic and should either
+be omitted or set to ``root``.
+
++-------------------------+-------------------------+-------------------------+
+| Attribute               | Datatype                | Semantics               |
++=========================+=========================+=========================+
+| srcmacaddr              | MAC_ADDR                | MAC address of sender   |
++-------------------------+-------------------------+-------------------------+
+| srcipaddr               | IPV6_ADDR               | Source IPv6 address     |
++-------------------------+-------------------------+-------------------------+
+| srcipmask               | IPV6_MASK               | Mask applied to source  |
+|                         |                         | IPv6 address            |
++-------------------------+-------------------------+-------------------------+
+| dstipaddr               | IPV6_ADDR               | Destination IPv6        |
+|                         |                         | address                 |
++-------------------------+-------------------------+-------------------------+
+| dstipmask               | IPV6_MASK               | Mask applied to         |
+|                         |                         | destination IPv6        |
+|                         |                         | address                 |
++-------------------------+-------------------------+-------------------------+
+| srcipfrom               | IPV6_ADDR               | Start of range of       |
+|                         |                         | source IP address       |
++-------------------------+-------------------------+-------------------------+
+| srcipto                 | IPV6_ADDR               | End of range of source  |
+|                         |                         | IP address              |
++-------------------------+-------------------------+-------------------------+
+| dstipfrom               | IPV6_ADDR               | Start of range of       |
+|                         |                         | destination IP address  |
++-------------------------+-------------------------+-------------------------+
+| dstipto                 | IPV6_ADDR               | End of range of         |
+|                         |                         | destination IP address  |
++-------------------------+-------------------------+-------------------------+
+| dscp                    | UINT8 (0x0-0x3f, 0 -    | Differentiated Services |
+|                         | 63)                     | Code Point              |
++-------------------------+-------------------------+-------------------------+
+| comment :since:`(Since  | STRING                  | text with max. 256      |
+| 0.8.5)`                 |                         | characters              |
++-------------------------+-------------------------+-------------------------+
+| state :since:`(Since    | STRING                  | comma separated list of |
+| 0.8.5)`                 |                         | NEW,ESTA                |
+|                         |                         | BLISHED,RELATED,INVALID |
+|                         |                         | or NONE                 |
++-------------------------+-------------------------+-------------------------+
+| ipset :since:`(Since    | STRING                  | The name of an IPSet    |
+| 0.9.13)`                |                         | managed outside of      |
+|                         |                         | libvirt                 |
++-------------------------+-------------------------+-------------------------+
+| ipsetflags              | IPSETFLAGS              | flags for the IPSet;    |
+| :since:`(Since 0.9.13)` |                         | requires ipset          |
+|                         |                         | attribute               |
++-------------------------+-------------------------+-------------------------+
+
+Advanced Filter Configuration Topics
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The following sections discuss advanced filter configuration topics.
+
+Connection tracking
+^^^^^^^^^^^^^^^^^^^
+
+The network filtering subsystem (on Linux) makes use of the connection tracking
+support of iptables. This helps in enforcing the directionality of network
+traffic (state match) as well as counting and limiting the number of
+simultaneous connections towards a VM. As an example, if a VM has TCP port 8080
+open as a server, clients may connect to the VM on port 8080. Connection
+tracking and enforcement of directionality then prevents the VM from initiating
+a connection from (TCP client) port 8080 to the host back to a remote host. More
+importantly, tracking helps to prevent remote attackers from establishing a
+connection back to a VM. For example, if the user inside the VM established a
+connection to port 80 on an attacker site, then the attacker will not be able to
+initiate a connection from TCP port 80 back towards the VM. By default the
+connection state match that enables connection tracking and then enforcement of
+directionality of traffic is turned on.
+
+The following shows an example XML fragment where this feature has been turned
+off for incoming connections to TCP port 12345.
+
+::
+
+   [...]
+   <rule direction='in' action='accept' statematch='false'>
+     <tcp dstportstart='12345'/>
+   </rule>
+   [...]
+
+This now allows incoming traffic to TCP port 12345, but would also enable the
+initiation from (client) TCP port 12345 within the VM, which may or may not be
+desirable.
+
+Limiting Number of Connections
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+To limit the number of connections a VM may establish, a rule must be provided
+that sets a limit of connections for a given type of traffic. If for example a
+VM is supposed to be allowed to only ping one other IP address at a time and is
+supposed to have only one active incoming ssh connection at a time, the
+following XML fragment can be used to achieve this.
+
+::
+
+   [...]
+   <rule action='drop' direction='in' priority='400'>
+     <tcp connlimit-above='1'/>
+   </rule>
+   <rule action='accept' direction='in' priority='500'>
+     <tcp dstportstart='22'/>
+   </rule>
+   <rule action='drop' direction='out' priority='400'>
+     <icmp connlimit-above='1'/>
+   </rule>
+   <rule action='accept' direction='out' priority='500'>
+     <icmp/>
+   </rule>
+   <rule action='accept' direction='out' priority='500'>
+     <udp dstportstart='53'/>
+   </rule>
+   <rule action='drop' direction='inout' priority='1000'>
+     <all/>
+   </rule>
+   [...]
+
+Note that the rule for the limit has to logically appear before the rule for
+accepting the traffic.
+
+An additional rule for letting DNS traffic to port 22 go out the VM has been
+added to avoid ssh sessions not getting established for reasons related to DNS
+lookup failures by the ssh daemon. Leaving this rule out may otherwise lead to
+fun-filled debugging joy (symptom: ssh client seems to hang while trying to
+connect).
+
+Lot of care must be taken with timeouts related to tracking of traffic. An ICMP
+ping that the user may have terminated inside the VM may have a long timeout in
+the host's connection tracking system and therefore not allow another ICMP ping
+to go through for a while. Therefore, the timeouts have to be tuned in the
+host's sysfs, i.e.,
+
+::
+
+   echo 3 > /proc/sys/net/netfilter/nf_conntrack_icmp_timeout
+
+sets the ICMP connection tracking timeout to 3 seconds. The effect of this is
+that once one ping is terminated, another one can start after 3 seconds.
+
+Further, we want to point out that a client that for whatever reason has not
+properly closed a TCP connection may cause a connection to be held open for a
+longer period of time, depending to what timeout the ``TCP established`` state
+timeout has been set to on the host. Also, idle connections may time out in the
+connection tracking system but can be reactivated once packets are exchanged.
+However, a newly initiated connection may force an idle connection into TCP
+backoff if the number of allowed connections is set to a too low limit, the new
+connection is established and hits (not exceeds) the limit of allowed
+connections and for example a key is pressed on the old ssh session, which now
+has become unresponsive due to its traffic being dropped. Therefore, the limit
+of connections should be rather high so that fluctuations in new TCP connections
+don't cause odd traffic behavior in relation to idle connections.
+
+Command line tools
+------------------
+
+The libvirt command line tool ``virsh`` has been extended with life-cycle
+support for network filters. All commands related to the network filtering
+subsystem start with the prefix ``nwfilter``. The following commands are
+available:
+
+-  nwfilter-list : list UUIDs and names of all network filters
+
+-  nwfilter-define : define a new network filter or update an existing one
+
+-  nwfilter-undefine : delete a network filter given its name; it must not be
+   currently in use
+
+-  nwfilter-dumpxml : display a network filter given its name
+
+-  nwfilter-edit : edit a network filter given its name
+
+Pre-existing network filters
+----------------------------
+
+The following is a list of example network filters that are automatically
+installed with libvirt.
+
++---------------------+-------------------------------------------------------+
+| Name                | Description                                           |
++=====================+=======================================================+
+| no-arp-spoofing     | Prevent a VM from spoofing ARP traffic; this filter   |
+|                     | only allows ARP request and reply messages and        |
+|                     | enforces that those packets contain the MAC and IP    |
+|                     | addresses of the VM.                                  |
++---------------------+-------------------------------------------------------+
+| allow-arp           | Allow ARP traffic in both directions                  |
++---------------------+-------------------------------------------------------+
+| allow-ipv4          | Allow IPv4 traffic in both directions                 |
++---------------------+-------------------------------------------------------+
+| allow-ipv6          | Allow IPv6 traffic in both directions                 |
++---------------------+-------------------------------------------------------+
+| allow-incoming-ipv4 | Allow incoming IPv4 traffic                           |
++---------------------+-------------------------------------------------------+
+| allow-incoming-ipv6 | Allow incoming IPv6 traffic                           |
++---------------------+-------------------------------------------------------+
+| allow-dhcp          | Allow a VM to request an IP address via DHCP (from    |
+|                     | any DHCP server)                                      |
++---------------------+-------------------------------------------------------+
+| allow-dhcpv6        | Similar to allow-dhcp, but for DHCPv6                 |
++---------------------+-------------------------------------------------------+
+| allow-dhcp-server   | Allow a VM to request an IP address from a specified  |
+|                     | DHCP server. The dotted decimal IP address of the     |
+|                     | DHCP server must be provided in a reference to this   |
+|                     | filter. The name of the variable must be              |
+|                     | *DHCPSERVER*.                                         |
++---------------------+-------------------------------------------------------+
+| allow-dhcpv6-server | Similar to allow-dhcp-server, but for DHCPv6          |
++---------------------+-------------------------------------------------------+
+| no-ip-spoofing      | Prevent a VM from sending of IPv4 packets with a      |
+|                     | source IP address different from the one in the       |
+|                     | packet.                                               |
++---------------------+-------------------------------------------------------+
+| no-ipv6-spoofing    | Similar to no-ip-spoofing, but for IPv6               |
++---------------------+-------------------------------------------------------+
+| no-ip-multicast     | Prevent a VM from sending IP multicast packets.       |
++---------------------+-------------------------------------------------------+
+| no-ipv6-multicast   | Similar to no-ip-multicast, but for IPv6              |
++---------------------+-------------------------------------------------------+
+| clean-traffic       | Prevent MAC, IP and ARP spoofing. This filter         |
+|                     | references several other filters as building blocks.  |
++---------------------+-------------------------------------------------------+
+
+Note that most of the above filters are only building blocks and require a
+combination with other filters to provide useful network traffic filtering. The
+most useful one in the above list is the *clean-traffic* filter. This filter
+itself can for example be combined with the *no-ip-multicast* filter to prevent
+virtual machines from sending IP multicast traffic on top of the prevention of
+packet spoofing.
+
+Writing your own filters
+------------------------
+
+Since libvirt only provides a couple of example networking filters, you may
+consider writing your own. When planning on doing so there are a couple of
+things you may need to know regarding the network filtering subsystem and how it
+works internally. Certainly you also have to know and understand the protocols
+very well that you want to be filtering on so that no further traffic than what
+you want can pass and that in fact the traffic you want to allow does pass.
+
+The network filtering subsystem is currently only available on Linux hosts and
+only works for QEMU and KVM type of virtual machines. On Linux it builds upon
+the support for ``ebtables``, ``iptables`` and ``ip6tables`` and makes use of
+their features. From the above list of supported protocols the following ones
+are implemented using ``ebtables``:
+
+-  mac
+
+-  stp (spanning tree protocol)
+
+-  vlan (802.1Q)
+
+-  arp, rarp
+
+-  ipv4
+
+-  ipv6
+
+All other protocols over IPv4 are supported using iptables, those over IPv6 are
+implemented using ip6tables.
+
+On a Linux host, all traffic filtering instantiated by libvirt's network filter
+subsystem first passes through the filtering support implemented by ebtables and
+only then through iptables or ip6tables filters. If a filter tree has rules with
+the protocols ``mac``, ``stp``, ``vlan`` ``arp``, ``rarp``, ``ipv4``, or
+``ipv6`` ebtables rules will automatically be instantiated.
+
+The role of the ``chain`` attribute in the network filter XML is that internally
+a new user-defined ebtables table is created that then for example receives all
+``arp`` traffic coming from or going to a virtual machine if the chain ``arp``
+has been specified. Further, a rule is generated in an interface's ``root``
+chain that directs all ipv4 traffic into the user-defined chain. Therefore, all
+ARP traffic rules should then be placed into filters specifying this chain. This
+type of branching into user-defined tables is only supported with filtering on
+the ebtables layer.
+
+:since:`Since 0.9.8` multiple chains for the same protocol can be created. For
+this the name of the chain must have a prefix of one of the previously
+enumerated protocols. To create an additional chain for handling of ARP traffic,
+a chain with name ``arp-test`` can be specified.
+
+As an example, it is possible to filter on UDP traffic by source and destination
+ports using the ``ip`` protocol filter and specifying attributes for the
+protocol, source and destination IP addresses and ports of UDP packets that are
+to be accepted. This allows early filtering of UDP traffic with ebtables.
+However, once an IP or IPv6 packet, such as a UDP packet, has passed the
+ebtables layer and there is at least one rule in a filter tree that instantiates
+iptables or ip6tables rules, a rule to let the UDP packet pass will also be
+necessary to be provided for those filtering layers. This can be achieved with a
+rule containing an appropriate ``udp`` or ``udp-ipv6`` traffic filtering node.
+
+Example custom filter
+~~~~~~~~~~~~~~~~~~~~~
+
+As an example we want to now build a filter that fulfills the following list of
+requirements:
+
+-  prevents a VM's interface from MAC, IP and ARP spoofing
+
+-  opens only TCP ports 22 and 80 of a VM's interface
+
+-  allows the VM to send ping traffic from an interface but not let the VM be
+   pinged on the interface
+
+-  allows the VM to do DNS lookups (UDP towards port 53)
+
+The requirement to prevent spoofing is fulfilled by the existing
+``clean-traffic`` network filter, thus we will reference this filter from our
+custom filter.
+
+To enable traffic for TCP ports 22 and 80 we will add 2 rules to enable this
+type of traffic. To allow the VM to send ping traffic we will add a rule for
+ICMP traffic. For simplicity reasons we allow general ICMP traffic to be
+initiated from the VM, not just ICMP echo request and response messages. To then
+disallow all other traffic to reach or be initiated by the VM we will then need
+to add a rule that drops all other traffic. Assuming our VM is called *test* and
+the interface we want to associate our filter with is called *eth0*, we name our
+filter *test-eth0*. The result of these considerations is the following network
+filter XML:
+
+::
+
+   <filter name='test-eth0'>
+     <!-- reference the clean traffic filter to prevent
+          MAC, IP and ARP spoofing. By not providing
+          and IP address parameter, libvirt will detect the
+          IP address the VM is using. -->
+     <filterref filter='clean-traffic'/>
+
+     <!-- enable TCP ports 22 (ssh) and 80 (http) to be reachable -->
+     <rule action='accept' direction='in'>
+       <tcp dstportstart='22'/>
+     </rule>
+
+     <rule action='accept' direction='in'>
+       <tcp dstportstart='80'/>
+     </rule>
+
+     <!-- enable general ICMP traffic to be initiated by the VM;
+          this includes ping traffic -->
+     <rule action='accept' direction='out'>
+       <icmp/>
+     </rule>
+
+     <!-- enable outgoing DNS lookups using UDP -->
+     <rule action='accept' direction='out'>
+       <udp dstportstart='53'/>
+     </rule>
+
+     <!-- drop all other traffic -->
+     <rule action='drop' direction='inout'>
+       <all/>
+     </rule>
+
+   </filter>
+
+Note that none of the rules in the above XML contain the IP address of the VM as
+either source or destination address, yet the filtering of the traffic works
+correctly. The reason is that the evaluation of the rules internally happens on
+a per-interface basis and the rules are evaluated based on the knowledge about
+which (tap) interface has sent or will receive the packet rather than what their
+source or destination IP address may be.
+
+An XML fragment for a possible network interface description inside the domain
+XML of the ``test`` VM could then look like this:
+
+::
+
+   [...]
+   <interface type='bridge'>
+     <source bridge='mybridge'/>
+     <filterref filter='test-eth0'/>
+   </interface>
+   [...]
+
+To more strictly control the ICMP traffic and enforce that only ICMP echo
+requests can be sent from the VM and only ICMP echo responses be received by the
+VM, the above ``ICMP`` rule can be replaced with the following two rules:
+
+::
+
+   <!-- enable outgoing ICMP echo requests-->
+   <rule action='accept' direction='out'>
+     <icmp type='8'/>
+   </rule>
+
+   <!-- enable incoming ICMP echo replies-->
+   <rule action='accept' direction='in'>
+     <icmp type='0'/>
+   </rule>
+
+Second example custom filter
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In this example we now want to build a similar filter as in the example above,
+but extend the list of requirements with an ftp server located inside the VM.
+Further, we will be using features that have been added in :since:`version
+0.8.5` . The requirements for this filter are:
+
+-  prevents a VM's interface from MAC, IP and ARP spoofing
+
+-  opens only TCP ports 22 and 80 of a VM's interface
+
+-  allows the VM to send ping traffic from an interface but not let the VM be
+   pinged on the interface
+
+-  allows the VM to do DNS lookups (UDP towards port 53)
+
+-  enable an ftp server (in active mode) to be run inside the VM
+
+The additional requirement of allowing an ftp server to be run inside the VM
+maps into the requirement of allowing port 21 to be reachable for ftp control
+traffic as well as enabling the VM to establish an outgoing tcp connection
+originating from the VM's TCP port 20 back to the ftp client (ftp active mode).
+There are several ways of how this filter can be written and we present 2
+solutions.
+
+The 1st solution makes use of the ``state`` attribute of the TCP protocol that
+gives us a hook into the connection tracking framework of the Linux host. For
+the VM-initiated ftp data connection (ftp active mode) we use the ``RELATED``
+state that allows us to detect that the VM-initiated ftp data connection is a
+consequence of ( or 'has a relationship with' ) an existing ftp control
+connection, thus we want to allow it to let packets pass the firewall. The
+``RELATED`` state, however, is only valid for the very first packet of the
+outgoing TCP connection for the ftp data path. Afterwards, the state to compare
+against is ``ESTABLISHED``, which then applies equally to the incoming and
+outgoing direction. All this is related to the ftp data traffic originating from
+TCP port 20 of the VM. This then leads to the following solution :since:`(since
+0.8.5 (QEMU, KVM))` :
+
+::
+
+   <filter name='test-eth0'>
+     <!-- reference the clean traffic filter to prevent
+          MAC, IP and ARP spoofing. By not providing
+          and IP address parameter, libvirt will detect the
+          IP address the VM is using. -->
+     <filterref filter='clean-traffic'/>
+
+     <!-- enable TCP port 21 (ftp-control) to be reachable -->
+     <rule action='accept' direction='in'>
+       <tcp dstportstart='21'/>
+     </rule>
+
+     <!-- enable TCP port 20 for VM-initiated ftp data connection
+          related to an existing ftp control connection -->
+     <rule action='accept' direction='out'>
+       <tcp srcportstart='20' state='RELATED,ESTABLISHED'/>
+     </rule>
+
+     <!-- accept all packets from client on the ftp data connection -->
+     <rule action='accept' direction='in'>
+       <tcp dstportstart='20' state='ESTABLISHED'/>
+     </rule>
+
+     <!-- enable TCP ports 22 (ssh) and 80 (http) to be reachable -->
+     <rule action='accept' direction='in'>
+       <tcp dstportstart='22'/>
+     </rule>
+
+     <rule action='accept' direction='in'>
+       <tcp dstportstart='80'/>
+     </rule>
+
+     <!-- enable general ICMP traffic to be initiated by the VM;
+          this includes ping traffic -->
+     <rule action='accept' direction='out'>
+       <icmp/>
+     </rule>
+
+     <!-- enable outgoing DNS lookups using UDP -->
+     <rule action='accept' direction='out'>
+       <udp dstportstart='53'/>
+     </rule>
+
+     <!-- drop all other traffic -->
+     <rule action='drop' direction='inout'>
+       <all/>
+     </rule>
+
+   </filter>
+
+Before trying out a filter using the ``RELATED`` state, you have to make sure
+that the appropriate connection tracking module has been loaded into the host's
+kernel. Depending on the version of the kernel, you must run either one of the
+following two commands before the ftp connection with the VM is established.
+
+::
+
+   modprobe nf_conntrack_ftp   # where available  or
+
+   modprobe ip_conntrack_ftp   # if above is not available
+
+If other protocols than ftp are to be used in conjunction with the ``RELATED``
+state, their corresponding module must be loaded. Modules exist at least for the
+protocols ftp, tftp, irc, sip, sctp, and amanda.
+
+The 2nd solution makes uses the state flags of connections more than the
+previous solution did. In this solution we take advantage of the fact that the
+``NEW`` state of a connection is valid when the very first packet of a traffic
+flow is seen. Subsequently, if the very first packet of a flow is accepted, the
+flow becomes a connection and enters the ``ESTABLISHED`` state. This allows us
+to write a general rule for allowing packets of ``ESTABLISHED`` connections to
+reach the VM or be sent by the VM. We write specific rules for the very first
+packets identified by the ``NEW`` state and for which ports they are acceptable.
+All packets for ports that are not explicitly accepted will be dropped and
+therefore the connection will not go into the ``ESTABLISHED`` state and any
+subsequent packets be dropped.
+
+::
+
+   <filter name='test-eth0'>
+     <!-- reference the clean traffic filter to prevent
+          MAC, IP and ARP spoofing. By not providing
+          and IP address parameter, libvirt will detect the
+          IP address the VM is using. -->
+     <filterref filter='clean-traffic'/>
+
+     <!-- let the packets of all previously accepted connections reach the VM -->
+     <rule action='accept' direction='in'>
+       <all state='ESTABLISHED'/>
+     </rule>
+
+     <!-- let the packets of all previously accepted and related connections be sent from the VM -->
+     <rule action='accept' direction='out'>
+       <all state='ESTABLISHED,RELATED'/>
+     </rule>
+
+     <!-- enable traffic towards port 21 (ftp), 22 (ssh) and 80 (http) -->
+     <rule action='accept' direction='in'>
+       <tcp dstportstart='21' dstportend='22' state='NEW'/>
+     </rule>
+
+     <rule action='accept' direction='in'>
+       <tcp dstportstart='80' state='NEW'/>
+     </rule>
+
+     <!-- enable general ICMP traffic to be initiated by the VM;
+          this includes ping traffic -->
+     <rule action='accept' direction='out'>
+       <icmp state='NEW'/>
+     </rule>
+
+     <!-- enable outgoing DNS lookups using UDP -->
+     <rule action='accept' direction='out'>
+       <udp dstportstart='53' state='NEW'/>
+     </rule>
+
+     <!-- drop all other traffic -->
+     <rule action='drop' direction='inout'>
+       <all/>
+     </rule>
+
+   </filter>
+
+Limitations
+-----------
+
+The following sections list (current) limitations of the network filtering
+subsystem.
+
+VM Migration
+~~~~~~~~~~~~
+
+VM migration is only supported if the whole filter tree that is referenced by a
+virtual machine's top level filter is also available on the target host. The
+network filter *clean-traffic* for example should be available on all libvirt
+installations of version 0.8.1 or later and thus enable migration of VMs that
+for example reference this filter. All other custom filters must be migrated
+using higher layer software. It is outside the scope of libvirt to ensure that
+referenced filters on the source system are equivalent to those on the target
+system and vice versa.
+
+Migration must occur between libvirt installations of version 0.8.1 or later in
+order not to lose the network traffic filters associated with an interface.
+
+VLAN filtering on Linux
+~~~~~~~~~~~~~~~~~~~~~~~
+
+VLAN (802.1Q) packets, if sent by a virtual machine, cannot be filtered with
+rules for protocol IDs ``arp``, ``rarp``, ``ipv4`` and ``ipv6`` but only with
+protocol IDs ``mac`` and ``vlan``. Therefore, the example filter
+``clean-traffic`` will not work as expected.
diff --git a/docs/meson.build b/docs/meson.build
index a8e360c8a4..0458eea683 100644
--- a/docs/meson.build
+++ b/docs/meson.build
@@ -21,7 +21,6 @@ docs_html_in_files = [
   'formatcaps',
   'formatnetwork',
   'formatnode',
-  'formatnwfilter',
   'index',
   'remote',
   'storage',
@@ -74,6 +73,7 @@ docs_rst_files = [
   'formatdomain',
   'formatdomaincaps',
   'formatnetworkport',
+  'formatnwfilter',
   'formatsecret',
   'formatsnapshot',
   'formatstorage',
-- 
2.35.1



More information about the libvir-list mailing list