9119d9
From f5ee5251bed8e5ff62d58dd6e8ee56b29b6ce3b4 Mon Sep 17 00:00:00 2001
9119d9
Message-Id: <f5ee5251bed8e5ff62d58dd6e8ee56b29b6ce3b4@dist-git>
9119d9
From: Laine Stump <laine@laine.org>
9119d9
Date: Mon, 15 Dec 2014 10:51:31 -0500
9119d9
Subject: [PATCH] qemu: setup tap devices for macTableManager='libvirt'
9119d9
9119d9
This is part of the fix for:
9119d9
9119d9
  https://bugzilla.redhat.com/show_bug.cgi?id=1099210
9119d9
9119d9
When libvirt is managing the MAC table of a Linux host bridge, it must
9119d9
turn off learning and unicast_flood for each tap device attached to
9119d9
that bridge, then add a Forwarding Database (fdb) entry for the tap
9119d9
device using the MAC address from the domain interface config.
9119d9
9119d9
Once we have disabled learning and flooding, any packet that has a
9119d9
destination MAC address not present in the fdb will be dropped by the
9119d9
bridge. This, along with the opportunistic disabling of promiscuous
9119d9
mode[*], can result in enhanced network performance. and a potential
9119d9
slight security improvement.
9119d9
9119d9
[*] If there is only one device on the bridge with learning/unicast_flood
9119d9
enabled, then that device will automatically have promiscuous mode
9119d9
disabled. If there are *no* devices with learning/unicast_flood
9119d9
enabled (e.g. for a libvirt "route", "nat", or isolated network that
9119d9
has no physical device attached), then all non-tap devices will have
9119d9
promiscuous mode disabled (tap devices always have promiscuous mode
9119d9
enabled, which may be a bug in the kernel, but in practice has 0
9119d9
effect).
9119d9
9119d9
None of this has any effect for kernels prior to 3.15 (upstream kernel
9119d9
commit 2796d0c648c940b4796f84384fbcfb0a2399db84 "bridge: Automatically
9119d9
manage port promiscuous mode"). Even after that, until kernel 3.17
9119d9
(upstream commit 5be5a2df40f005ea7fb7e280e87bbbcfcf1c2fc0 "bridge: Add
9119d9
filtering support for default_pvid") traffic will not be properly
9119d9
forwarded without manually adding vlan table entries. Unfortunately,
9119d9
although the presence of the first patch is signalled by existence of
9119d9
the "learning" and "unicast_flood" options in sysfs, there is no
9119d9
reliable way to query whether or not the system's kernel has the
9119d9
second of those patches installed, the only thing that can be done is
9119d9
to try the setting and see if traffic continues to pass.
9119d9
9119d9
(cherry picked from commit 7cb822c2a5f697823764aee94524243e8ed5e165)
9119d9
9119d9
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
9119d9
---
9119d9
 src/qemu/qemu_command.c | 19 +++++++++++++++++++
9119d9
 1 file changed, 19 insertions(+)
9119d9
9119d9
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
9119d9
index cd87812..a9c4271 100644
9119d9
--- a/src/qemu/qemu_command.c
9119d9
+++ b/src/qemu/qemu_command.c
9119d9
@@ -35,6 +35,7 @@
9119d9
 #include "virerror.h"
9119d9
 #include "virfile.h"
9119d9
 #include "virnetdev.h"
9119d9
+#include "virnetdevbridge.h"
9119d9
 #include "virstring.h"
9119d9
 #include "virtime.h"
9119d9
 #include "viruuid.h"
9119d9
@@ -349,6 +350,24 @@ qemuNetworkIfaceConnect(virDomainDefPtr def,
9119d9
             virDomainAuditNetDevice(def, net, tunpath, false);
9119d9
             goto cleanup;
9119d9
         }
9119d9
+        if (virDomainNetGetActualBridgeMACTableManager(net)
9119d9
+            == VIR_NETWORK_BRIDGE_MAC_TABLE_MANAGER_LIBVIRT) {
9119d9
+            /* libvirt is managing the FDB of the bridge this device
9119d9
+             * is attaching to, so we need to turn off learning and
9119d9
+             * unicast_flood on the device to prevent the kernel from
9119d9
+             * adding any FDB entries for it, then add an fdb entry
9119d9
+             * outselves, using the MAC address from the interface
9119d9
+             * config.
9119d9
+             */
9119d9
+            if (virNetDevBridgePortSetLearning(brname, net->ifname, false) < 0)
9119d9
+                goto cleanup;
9119d9
+            if (virNetDevBridgePortSetUnicastFlood(brname, net->ifname, false) < 0)
9119d9
+                goto cleanup;
9119d9
+            if (virNetDevBridgeFDBAdd(&net->mac, net->ifname,
9119d9
+                                      VIR_NETDEVBRIDGE_FDB_FLAG_MASTER |
9119d9
+                                      VIR_NETDEVBRIDGE_FDB_FLAG_TEMP) < 0)
9119d9
+                goto cleanup;
9119d9
+        }
9119d9
     } else {
9119d9
         if (qemuCreateInBridgePortWithHelper(cfg, brname,
9119d9
                                              &net->ifname,
9119d9
-- 
9119d9
2.2.0
9119d9