[libvirt] [PATCH 00/26] Rewrite firewall code to use formal API

Daniel P. Berrange berrange at redhat.com
Tue Apr 8 15:37:52 UTC 2014


Currently we have three places which interact with the firewall

  - util/virebtables - simple MAC filtering used by QEMU driver
  - util/viriptables - used by network driver
  - nwfilter - general purpose guest filtering

All of these have been hacked to support firewalld by re-directing
them via the 'firewall-cmd' command line tool. Unfortunately talking
to firewalld via this CLI tool is incredibly inefficient.

eg timing the network driver

 $ for i in `seq 1 10` ; do virsh net-start default; virsh net-destroy default ; done

   Direct iptables:  3 seconds
  Via firewall-cmd: 42 seconds

Or timing the nwfilter driver via libvirt-tck/scripts/nwfilter/050-apply-verify-host.t

   Direct iptables: 28 seconds
  Via firewall-cmd: 479 seconds

IOW it is more than x10 slower to use firewall-cmd.


Testing revealed that this performance penalty is entirely due to the
'firewall-cmd' command line tool. If you talk directly to firewalld
over DBus then the performance is near native.

Unfortunately switching to use the DBus API is non-trivial since all
the code we have for interacting with the firewall is just constructing
virCommand instances directly (viriptables) or constructing gross shell
scripts (nwfilter).

Thus to enable use of the DBus API this series introduces the concept of
a new object and APIs for interacting with the firewall "virFirewall". 
This API is designed to be a fairly generic basis for interacting with
any firewall. It just has a concept of a level (ethernet, ipv4 or ipv6)
and lists of rules, where each rule is just a string array of args. The
idea is that the mechanism for interacting with the firewall can be
generic and portable, even though the actual rules will be different on
Linux vs FreeBSD vs other OS.

The initial virFirewall implementation supports direct iptables/ebtables
invocation or the DBus firewalld API. Use of firewall-cmd has been killed
completely.

Adapting code to use virFirewall has been a pretty horrific job, so is
split up into as many patches as is practical. By far the worst/hardest
patch is the one for nwfilter applyNewRules method (patch 23).  Fortunately
the libvirt-tck has a large set of XML data files and corresponding
expected iptables/ebtables rules. This series passes the libvirt-tck 100%
before and after, so I'm fairly confident that all the core functionality is
working correctly.

I also introduced new unit tests, that re-use the XML files from the
libvirt-tck to validate the actual iptables/ebtables commands that libvirt
tests. I've run this unit test under valgrind and under the OOM simulator
to identify and fix any crashes / leaks that the refactoring introduced.

With this series applied the performance is vastly improved for firewalld

eg timing the network driver

 $ for i in `seq 1 10` ; do virsh net-start default; virsh net-destroy default ; done

   Direct iptables:  3 seconds
  Via firewall-cmd:  3 seconds

Or timing the nwfilter driver via libvirt-tck/scripts/nwfilter/050-apply-verify-host.t

   Direct iptables: 29 seconds
  Via firewall-cmd: 37 seconds

IOW firewalld is only marginly slower than direct iptables usage now.

Regards,
Daniel

Daniel P. Berrange (26):
  Move virNWFilterTechDriver struct out of nwfilter_conf.h
  Remove virDomainNetType parameter from nwfilter drivers
  Remove pointless storage of var names in virNWFilterHashTable
  Remove nwfilter tech driver 'removeRules' callback
  Remove nwfilter tech driver 'displayRuleInstance' callback
  Add helper methods for determining what protocol layer is used
  Push virNWFilterRuleInstPtr out of (eb|ip)tablesCreateRuleInstance
  Merge nwfilter createRuleInstance driver into applyNewRules
  Remove two-stage construction of commands in nwfilter
  Preserve error when tearing down nwfilter rules
  Introduce an object for managing firewall rulesets
  Convert bridge driver over to use new firewall APIs
  Replace virNetworkObjPtr with virNetworkDefPtr in network platform
    APIs
  Add test for converting network XML to iptables rules
  Convert ebtables code over to use firewall APIs
  Convert nwfilter ebiptablesAllTeardown to virFirewall
  Convert nwfilter ebiptablesTearOldRules to virFirewall
  Convert nwfilter ebtablesRemoveBasicRules to virFirewall
  Convert nwfilter ebiptablesTearNewRules to virFirewall
  Convert nwfilter ebtablesApplyBasicRules to virFirewall
  Convert nwfilter ebtablesApplyDHCPOnlyRules to virFirewall
  Convert nwfilter ebtablesApplyDropAllRules to virFirewall
  Convert nwfilter ebiptablesApplyNewRules to virFirewall
  Convert ebiptablesDriverProbeStateMatch to virFirewall
  Remove last trace of direct firewall command exection
  Add a test suite for nwfilter ebiptables tech driver

 include/libvirt/virterror.h                        |    1 +
 po/POTFILES.in                                     |    1 +
 src/Makefile.am                                    |   21 +-
 src/conf/nwfilter_conf.c                           |   49 +-
 src/conf/nwfilter_conf.h                           |  107 +-
 src/conf/nwfilter_ipaddrmap.c                      |    2 +-
 src/conf/nwfilter_params.c                         |   63 +-
 src/conf/nwfilter_params.h                         |    7 +-
 src/libvirt_private.syms                           |   22 +
 src/network/bridge_driver.c                        |   18 +-
 src/network/bridge_driver_linux.c                  |  757 ++--
 src/network/bridge_driver_nop.c                    |    6 +-
 src/network/bridge_driver_platform.h               |    7 +-
 src/nwfilter/nwfilter_dhcpsnoop.c                  |    6 -
 src/nwfilter/nwfilter_dhcpsnoop.h                  |    3 +-
 src/nwfilter/nwfilter_ebiptables_driver.c          | 3867 ++++++++------------
 src/nwfilter/nwfilter_ebiptables_driver.h          |   19 +-
 src/nwfilter/nwfilter_gentech_driver.c             |  415 +--
 src/nwfilter/nwfilter_gentech_driver.h             |    2 +-
 src/nwfilter/nwfilter_learnipaddr.c                |    5 -
 src/nwfilter/nwfilter_learnipaddr.h                |    3 +-
 src/nwfilter/nwfilter_tech_driver.h                |   96 +
 src/qemu/qemu_command.c                            |    6 +-
 src/util/virebtables.c                             |  185 +-
 src/util/virerror.c                                |    1 +
 src/util/virfirewall.c                             |  922 +++++
 src/util/virfirewall.h                             |  109 +
 src/util/virfirewallpriv.h                         |   45 +
 src/util/viriptables.c                             |  632 ++--
 src/util/viriptables.h                             |  114 +-
 tests/Makefile.am                                  |   42 +-
 .../networkxml2firewalldata/nat-default-linux.args |   30 +
 tests/networkxml2firewalldata/nat-default.xml      |   10 +
 tests/networkxml2firewalldata/nat-ipv6-linux.args  |   44 +
 tests/networkxml2firewalldata/nat-ipv6.xml         |   15 +
 .../nat-many-ips-linux.args                        |   58 +
 tests/networkxml2firewalldata/nat-many-ips.xml     |   12 +
 .../networkxml2firewalldata/nat-no-dhcp-linux.args |   42 +
 tests/networkxml2firewalldata/nat-no-dhcp.xml      |    7 +
 tests/networkxml2firewalldata/nat-tftp-linux.args  |   32 +
 tests/networkxml2firewalldata/nat-tftp.xml         |   11 +
 .../route-default-linux.args                       |   20 +
 tests/networkxml2firewalldata/route-default.xml    |   10 +
 tests/networkxml2firewalltest.c                    |  162 +
 tests/nwfilterebiptablestest.c                     |  548 +++
 tests/nwfilterxml2firewalldata/ah-ipv6-linux.args  |   20 +
 tests/nwfilterxml2firewalldata/ah-ipv6.xml         |   19 +
 tests/nwfilterxml2firewalldata/ah-linux.args       |   18 +
 tests/nwfilterxml2firewalldata/ah.xml              |   18 +
 tests/nwfilterxml2firewalldata/all-ipv6-linux.args |   20 +
 tests/nwfilterxml2firewalldata/all-ipv6.xml        |   19 +
 tests/nwfilterxml2firewalldata/all-linux.args      |   18 +
 tests/nwfilterxml2firewalldata/all.xml             |   18 +
 tests/nwfilterxml2firewalldata/arp-linux.args      |   11 +
 tests/nwfilterxml2firewalldata/arp.xml             |   32 +
 tests/nwfilterxml2firewalldata/comment-linux.args  |   49 +
 tests/nwfilterxml2firewalldata/comment.xml         |   71 +
 .../nwfilterxml2firewalldata/conntrack-linux.args  |    7 +
 tests/nwfilterxml2firewalldata/conntrack.xml       |   12 +
 tests/nwfilterxml2firewalldata/esp-ipv6-linux.args |   20 +
 tests/nwfilterxml2firewalldata/esp-ipv6.xml        |   19 +
 tests/nwfilterxml2firewalldata/esp-linux.args      |   18 +
 tests/nwfilterxml2firewalldata/esp.xml             |   18 +
 .../nwfilterxml2firewalldata/example-1-linux.args  |   13 +
 tests/nwfilterxml2firewalldata/example-1.xml       |   24 +
 .../nwfilterxml2firewalldata/example-2-linux.args  |   20 +
 tests/nwfilterxml2firewalldata/example-2.xml       |   37 +
 tests/nwfilterxml2firewalldata/hex-data-linux.args |   28 +
 tests/nwfilterxml2firewalldata/hex-data.xml        |   56 +
 .../icmp-direction-linux.args                      |    9 +
 tests/nwfilterxml2firewalldata/icmp-direction.xml  |   15 +
 .../icmp-direction2-linux.args                     |    9 +
 tests/nwfilterxml2firewalldata/icmp-direction2.xml |   15 +
 .../icmp-direction3-linux.args                     |    6 +
 tests/nwfilterxml2firewalldata/icmp-direction3.xml |   10 +
 tests/nwfilterxml2firewalldata/icmp-linux.args     |    9 +
 tests/nwfilterxml2firewalldata/icmp.xml            |   13 +
 tests/nwfilterxml2firewalldata/icmpv6-linux.args   |   12 +
 tests/nwfilterxml2firewalldata/icmpv6.xml          |   19 +
 tests/nwfilterxml2firewalldata/igmp-linux.args     |   18 +
 tests/nwfilterxml2firewalldata/igmp.xml            |   18 +
 tests/nwfilterxml2firewalldata/ip-linux.args       |    8 +
 tests/nwfilterxml2firewalldata/ip.xml              |   28 +
 tests/nwfilterxml2firewalldata/ipset-linux.args    |   36 +
 tests/nwfilterxml2firewalldata/ipset.xml           |   25 +
 .../ipt-no-macspoof-linux.args                     |    2 +
 tests/nwfilterxml2firewalldata/ipt-no-macspoof.xml |   14 +
 tests/nwfilterxml2firewalldata/ipv6-linux.args     |   20 +
 tests/nwfilterxml2firewalldata/ipv6.xml            |   43 +
 tests/nwfilterxml2firewalldata/iter1-linux.args    |   18 +
 tests/nwfilterxml2firewalldata/iter1.xml           |    6 +
 tests/nwfilterxml2firewalldata/iter2-linux.args    |  342 ++
 tests/nwfilterxml2firewalldata/iter2.xml           |   23 +
 tests/nwfilterxml2firewalldata/iter3-linux.args    |   30 +
 tests/nwfilterxml2firewalldata/iter3.xml           |   13 +
 tests/nwfilterxml2firewalldata/mac-linux.args      |    8 +
 tests/nwfilterxml2firewalldata/mac.xml             |   19 +
 tests/nwfilterxml2firewalldata/rarp-linux.args     |   12 +
 tests/nwfilterxml2firewalldata/rarp.xml            |   28 +
 tests/nwfilterxml2firewalldata/ref-rule.xml        |   18 +
 tests/nwfilterxml2firewalldata/ref.xml             |    4 +
 .../nwfilterxml2firewalldata/sctp-ipv6-linux.args  |   22 +
 tests/nwfilterxml2firewalldata/sctp-ipv6.xml       |   22 +
 tests/nwfilterxml2firewalldata/sctp-linux.args     |   20 +
 tests/nwfilterxml2firewalldata/sctp.xml            |   22 +
 tests/nwfilterxml2firewalldata/stp-linux.args      |   18 +
 tests/nwfilterxml2firewalldata/stp.xml             |   26 +
 tests/nwfilterxml2firewalldata/target-linux.args   |   75 +
 tests/nwfilterxml2firewalldata/target.xml          |   66 +
 tests/nwfilterxml2firewalldata/target2-linux.args  |   13 +
 tests/nwfilterxml2firewalldata/target2.xml         |   18 +
 tests/nwfilterxml2firewalldata/tcp-ipv6-linux.args |   22 +
 tests/nwfilterxml2firewalldata/tcp-ipv6.xml        |   22 +
 tests/nwfilterxml2firewalldata/tcp-linux.args      |   22 +
 tests/nwfilterxml2firewalldata/tcp.xml             |   34 +
 tests/nwfilterxml2firewalldata/udp-ipv6-linux.args |   22 +
 tests/nwfilterxml2firewalldata/udp-ipv6.xml        |   22 +
 tests/nwfilterxml2firewalldata/udp-linux.args      |   20 +
 tests/nwfilterxml2firewalldata/udp.xml             |   22 +
 .../udplite-ipv6-linux.args                        |   20 +
 tests/nwfilterxml2firewalldata/udplite-ipv6.xml    |   19 +
 tests/nwfilterxml2firewalldata/udplite-linux.args  |   18 +
 tests/nwfilterxml2firewalldata/udplite.xml         |   18 +
 tests/nwfilterxml2firewalldata/vlan-linux.args     |   14 +
 tests/nwfilterxml2firewalldata/vlan.xml            |   38 +
 tests/nwfilterxml2firewalltest.c                   |  534 +++
 tests/testutils.c                                  |   18 +-
 tests/virfirewalltest.c                            | 1186 ++++++
 128 files changed, 8637 insertions(+), 3685 deletions(-)
 create mode 100644 src/nwfilter/nwfilter_tech_driver.h
 create mode 100644 src/util/virfirewall.c
 create mode 100644 src/util/virfirewall.h
 create mode 100644 src/util/virfirewallpriv.h
 create mode 100644 tests/networkxml2firewalldata/nat-default-linux.args
 create mode 100644 tests/networkxml2firewalldata/nat-default.xml
 create mode 100644 tests/networkxml2firewalldata/nat-ipv6-linux.args
 create mode 100644 tests/networkxml2firewalldata/nat-ipv6.xml
 create mode 100644 tests/networkxml2firewalldata/nat-many-ips-linux.args
 create mode 100644 tests/networkxml2firewalldata/nat-many-ips.xml
 create mode 100644 tests/networkxml2firewalldata/nat-no-dhcp-linux.args
 create mode 100644 tests/networkxml2firewalldata/nat-no-dhcp.xml
 create mode 100644 tests/networkxml2firewalldata/nat-tftp-linux.args
 create mode 100644 tests/networkxml2firewalldata/nat-tftp.xml
 create mode 100644 tests/networkxml2firewalldata/route-default-linux.args
 create mode 100644 tests/networkxml2firewalldata/route-default.xml
 create mode 100644 tests/networkxml2firewalltest.c
 create mode 100644 tests/nwfilterebiptablestest.c
 create mode 100644 tests/nwfilterxml2firewalldata/ah-ipv6-linux.args
 create mode 100644 tests/nwfilterxml2firewalldata/ah-ipv6.xml
 create mode 100644 tests/nwfilterxml2firewalldata/ah-linux.args
 create mode 100644 tests/nwfilterxml2firewalldata/ah.xml
 create mode 100644 tests/nwfilterxml2firewalldata/all-ipv6-linux.args
 create mode 100644 tests/nwfilterxml2firewalldata/all-ipv6.xml
 create mode 100644 tests/nwfilterxml2firewalldata/all-linux.args
 create mode 100644 tests/nwfilterxml2firewalldata/all.xml
 create mode 100644 tests/nwfilterxml2firewalldata/arp-linux.args
 create mode 100644 tests/nwfilterxml2firewalldata/arp.xml
 create mode 100644 tests/nwfilterxml2firewalldata/comment-linux.args
 create mode 100644 tests/nwfilterxml2firewalldata/comment.xml
 create mode 100644 tests/nwfilterxml2firewalldata/conntrack-linux.args
 create mode 100644 tests/nwfilterxml2firewalldata/conntrack.xml
 create mode 100644 tests/nwfilterxml2firewalldata/esp-ipv6-linux.args
 create mode 100644 tests/nwfilterxml2firewalldata/esp-ipv6.xml
 create mode 100644 tests/nwfilterxml2firewalldata/esp-linux.args
 create mode 100644 tests/nwfilterxml2firewalldata/esp.xml
 create mode 100644 tests/nwfilterxml2firewalldata/example-1-linux.args
 create mode 100644 tests/nwfilterxml2firewalldata/example-1.xml
 create mode 100644 tests/nwfilterxml2firewalldata/example-2-linux.args
 create mode 100644 tests/nwfilterxml2firewalldata/example-2.xml
 create mode 100644 tests/nwfilterxml2firewalldata/hex-data-linux.args
 create mode 100644 tests/nwfilterxml2firewalldata/hex-data.xml
 create mode 100644 tests/nwfilterxml2firewalldata/icmp-direction-linux.args
 create mode 100644 tests/nwfilterxml2firewalldata/icmp-direction.xml
 create mode 100644 tests/nwfilterxml2firewalldata/icmp-direction2-linux.args
 create mode 100644 tests/nwfilterxml2firewalldata/icmp-direction2.xml
 create mode 100644 tests/nwfilterxml2firewalldata/icmp-direction3-linux.args
 create mode 100644 tests/nwfilterxml2firewalldata/icmp-direction3.xml
 create mode 100644 tests/nwfilterxml2firewalldata/icmp-linux.args
 create mode 100644 tests/nwfilterxml2firewalldata/icmp.xml
 create mode 100644 tests/nwfilterxml2firewalldata/icmpv6-linux.args
 create mode 100644 tests/nwfilterxml2firewalldata/icmpv6.xml
 create mode 100644 tests/nwfilterxml2firewalldata/igmp-linux.args
 create mode 100644 tests/nwfilterxml2firewalldata/igmp.xml
 create mode 100644 tests/nwfilterxml2firewalldata/ip-linux.args
 create mode 100644 tests/nwfilterxml2firewalldata/ip.xml
 create mode 100644 tests/nwfilterxml2firewalldata/ipset-linux.args
 create mode 100644 tests/nwfilterxml2firewalldata/ipset.xml
 create mode 100644 tests/nwfilterxml2firewalldata/ipt-no-macspoof-linux.args
 create mode 100644 tests/nwfilterxml2firewalldata/ipt-no-macspoof.xml
 create mode 100644 tests/nwfilterxml2firewalldata/ipv6-linux.args
 create mode 100644 tests/nwfilterxml2firewalldata/ipv6.xml
 create mode 100644 tests/nwfilterxml2firewalldata/iter1-linux.args
 create mode 100644 tests/nwfilterxml2firewalldata/iter1.xml
 create mode 100644 tests/nwfilterxml2firewalldata/iter2-linux.args
 create mode 100644 tests/nwfilterxml2firewalldata/iter2.xml
 create mode 100644 tests/nwfilterxml2firewalldata/iter3-linux.args
 create mode 100644 tests/nwfilterxml2firewalldata/iter3.xml
 create mode 100644 tests/nwfilterxml2firewalldata/mac-linux.args
 create mode 100644 tests/nwfilterxml2firewalldata/mac.xml
 create mode 100644 tests/nwfilterxml2firewalldata/rarp-linux.args
 create mode 100644 tests/nwfilterxml2firewalldata/rarp.xml
 create mode 100644 tests/nwfilterxml2firewalldata/ref-rule.xml
 create mode 100644 tests/nwfilterxml2firewalldata/ref.xml
 create mode 100644 tests/nwfilterxml2firewalldata/sctp-ipv6-linux.args
 create mode 100644 tests/nwfilterxml2firewalldata/sctp-ipv6.xml
 create mode 100644 tests/nwfilterxml2firewalldata/sctp-linux.args
 create mode 100644 tests/nwfilterxml2firewalldata/sctp.xml
 create mode 100644 tests/nwfilterxml2firewalldata/stp-linux.args
 create mode 100644 tests/nwfilterxml2firewalldata/stp.xml
 create mode 100644 tests/nwfilterxml2firewalldata/target-linux.args
 create mode 100644 tests/nwfilterxml2firewalldata/target.xml
 create mode 100644 tests/nwfilterxml2firewalldata/target2-linux.args
 create mode 100644 tests/nwfilterxml2firewalldata/target2.xml
 create mode 100644 tests/nwfilterxml2firewalldata/tcp-ipv6-linux.args
 create mode 100644 tests/nwfilterxml2firewalldata/tcp-ipv6.xml
 create mode 100644 tests/nwfilterxml2firewalldata/tcp-linux.args
 create mode 100644 tests/nwfilterxml2firewalldata/tcp.xml
 create mode 100644 tests/nwfilterxml2firewalldata/udp-ipv6-linux.args
 create mode 100644 tests/nwfilterxml2firewalldata/udp-ipv6.xml
 create mode 100644 tests/nwfilterxml2firewalldata/udp-linux.args
 create mode 100644 tests/nwfilterxml2firewalldata/udp.xml
 create mode 100644 tests/nwfilterxml2firewalldata/udplite-ipv6-linux.args
 create mode 100644 tests/nwfilterxml2firewalldata/udplite-ipv6.xml
 create mode 100644 tests/nwfilterxml2firewalldata/udplite-linux.args
 create mode 100644 tests/nwfilterxml2firewalldata/udplite.xml
 create mode 100644 tests/nwfilterxml2firewalldata/vlan-linux.args
 create mode 100644 tests/nwfilterxml2firewalldata/vlan.xml
 create mode 100644 tests/nwfilterxml2firewalltest.c
 create mode 100644 tests/virfirewalltest.c

-- 
1.9.0




More information about the libvir-list mailing list