On 02/27/2014 12:37 PM, Roman Bogorodskiy wrote:
We have to explicitly destroy TAP devices on FreeBSD because
they're not freed after being closed, otherwise we end up with
orphaned TAP devices after destroying a domain.
---
src/qemu/qemu_process.c | 7 +++++++
src/util/virnetdevtap.h | 6 ++++++
2 files changed, 13 insertions(+)
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index ffa939a..6806539 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -61,6 +61,7 @@
#include "viruuid.h"
#include "virprocess.h"
#include "virtime.h"
+#include "virnetdevbridge.h"
#include "virnetdevtap.h"
#include "virbitmap.h"
#include "viratomic.h"
@@ -4381,6 +4382,12 @@ void qemuProcessStop(virQEMUDriverPtr driver,
virDomainNetGetActualVirtPortProfile(net),
cfg->stateDir));
VIR_FREE(net->ifname);
+#ifdef VIR_NETDEV_TAP_REQUIRE_MANUAL_CLEANUP
+ } else if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_BRIDGE) {
+
ignore_value(virNetDevBridgeRemovePort(virDomainNetGetActualBridgeName(net),
+ net->ifname));
+ ignore_value(virNetDevTapDelete(net->ifname));
+#endif
This is also needed if virDomainNetGetActualType(net) ==
VIR_DOMAIN_NET_TYPE_NETWORK (since a libvirt virtual network is
implemented using a bridge device connected to tap devices - see the
corresponding "create a tap device" code for a network device at
qemu_command.c:7562).
Since you would be calling the *Get function so many times, maybe it
would be better to use a switch statement.
Of course, the bridge device used by a VIR_DOMAIN_NET_TYPE_NETWORK
interface is *not* returned by virDomainNetGetActualBridgeName() (which
is intended to only be a simple wrapper around the interface config), so
you would need to use the code in the "actualType ==
VIR_DOMAIN_NET_TYPE_NETWORK" clause of qemuNetworkIfaceConnect() to
retrieve the appropriate network object and get the name of the bridge
it uses. (in other words - NETWORK and BRIDGE will need different cases
in the switch :-( ) (this is now done in enough places that perhaps it
is time for a helper function)
Also, notice that the code just below your addition is removing the tap
device from an openvswitch bridge if necessary - your patch would end up
calling the wrong function (virNetDevBridgeRemovePort) for interfaces
attached to an openvswitch port. I think you need to first get the
actualType and vport, then use the actualType to decide whether or not
to retrieve brname, and then the vport setting to decide if you need to
detach from an openvswitch port (always) or detach from a normal bridge
(freebsd only).
}
/* release the physical device (or any other resources used by
* this interface in the network driver
diff --git a/src/util/virnetdevtap.h b/src/util/virnetdevtap.h
index a762b31..1e5bd19 100644
--- a/src/util/virnetdevtap.h
+++ b/src/util/virnetdevtap.h
@@ -27,6 +27,12 @@
# include "virnetdevvportprofile.h"
# include "virnetdevvlan.h"
+# ifdef __FreeBSD__
+/* This should be defined on OSes that don't automatically
+ * cleanup released devices */
+# define VIR_NETDEV_TAP_REQUIRE_MANUAL_CLEANUP 1
+# endif
+
int virNetDevTapCreate(char **ifname,
int *tapfd,
int tapfdSize,