[libvirt] [PATCH 08/33] Split bridge.h into three separate files

Daniel P. Berrange berrange at redhat.com
Thu Nov 3 17:30:04 UTC 2011


From: "Daniel P. Berrange" <berrange at redhat.com>

Following the renaming of the bridge management APIs, we can now
split the source file into 3 corresponding pieces

 * src/util/virnetdev.c: APIs for any type of network interface
 * src/util/virnetdevbridge.c: APIs for bridge interfaces
 * src/util/virnetdevtap.c: APIs for TAP interfaces

* src/util/virnetdev.c, src/util/virnetdev.h,
  src/util/virnetdevbridge.c, src/util/virnetdevbridge.h,
  src/util/virnetdevtap.c, src/util/virnetdevtap.h: Copied
  from bridge.{c,h}
* src/util/bridge.c, src/util/bridge.h: Split into 3 pieces
* src/lxc/lxc_driver.c, src/network/bridge_driver.c,
  src/openvz/openvz_driver.c, src/qemu/qemu_command.c,
  src/qemu/qemu_conf.h, src/uml/uml_conf.c, src/uml/uml_conf.h,
  src/uml/uml_driver.c: Update #include directives
---
 configure.ac                |    3 +-
 po/POTFILES.in              |    4 +-
 src/Makefile.am             |    6 +-
 src/lxc/lxc_driver.c        |    2 +-
 src/network/bridge_driver.c |    5 +-
 src/openvz/openvz_driver.c  |    1 -
 src/qemu/qemu_command.c     |    1 +
 src/qemu/qemu_conf.h        |    1 -
 src/uml/uml_conf.c          |    2 +-
 src/uml/uml_conf.h          |    1 -
 src/uml/uml_driver.c        |    1 +
 src/util/bridge.c           | 1115 -------------------------------------------
 src/util/bridge.h           |  129 -----
 src/util/virnetdev.c        |  524 ++++++++++++++++++++
 src/util/virnetdev.h        |   63 +++
 src/util/virnetdevbridge.c  |  527 ++++++++++++++++++++
 src/util/virnetdevbridge.h  |   54 ++
 src/util/virnetdevtap.c     |  300 ++++++++++++
 src/util/virnetdevtap.h     |   45 ++
 19 files changed, 1530 insertions(+), 1254 deletions(-)
 delete mode 100644 src/util/bridge.c
 delete mode 100644 src/util/bridge.h
 create mode 100644 src/util/virnetdev.c
 create mode 100644 src/util/virnetdev.h
 create mode 100644 src/util/virnetdevbridge.c
 create mode 100644 src/util/virnetdevbridge.h
 create mode 100644 src/util/virnetdevtap.c
 create mode 100644 src/util/virnetdevtap.h

diff --git a/configure.ac b/configure.ac
index 0ce020d..c2746d8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -150,7 +150,8 @@ LIBS=$old_libs
 dnl Availability of various common headers (non-fatal if missing).
 AC_CHECK_HEADERS([pwd.h paths.h regex.h sys/un.h \
   sys/poll.h syslog.h mntent.h net/ethernet.h linux/magic.h \
-  sys/un.h sys/syscall.h netinet/tcp.h ifaddrs.h libtasn1.h])
+  sys/un.h sys/syscall.h netinet/tcp.h ifaddrs.h libtasn1.h \
+  net/if.h])
 
 dnl Our only use of libtasn1.h is in the testsuite, and can be skipped
 dnl if the header is not present.  Assume -ltasn1 is present if the
diff --git a/po/POTFILES.in b/po/POTFILES.in
index bd1d7bd..a3685e8 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -102,7 +102,6 @@ src/test/test_driver.c
 src/uml/uml_conf.c
 src/uml/uml_driver.c
 src/util/authhelper.c
-src/util/bridge.c
 src/util/cgroup.c
 src/util/command.c
 src/util/conf.c
@@ -127,6 +126,9 @@ src/util/sysinfo.c
 src/util/util.c
 src/util/viraudit.c
 src/util/virfile.c
+src/util/virnetdev.c
+src/util/virnetdevbridge.c
+src/util/virnetdevtap.c
 src/util/virpidfile.c
 src/util/virterror.c
 src/util/xml.c
diff --git a/src/Makefile.am b/src/Makefile.am
index bf26b19..f742f2a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -52,7 +52,6 @@ augeastest_DATA =
 UTIL_SOURCES =							\
 		util/authhelper.c util/authhelper.h		\
 		util/bitmap.c util/bitmap.h			\
-		util/bridge.c util/bridge.h			\
 		util/buf.c util/buf.h				\
 		util/command.c util/command.h			\
 		util/conf.c util/conf.h				\
@@ -91,7 +90,10 @@ UTIL_SOURCES =							\
 		util/xml.c util/xml.h				\
 		util/virterror.c util/virterror_internal.h	\
 		util/virkeycode.c util/virkeycode.h		\
-		util/virkeymaps.h
+		util/virkeymaps.h				\
+		util/virnetdev.h util/virnetdev.c		\
+		util/virnetdevbridge.h util/virnetdevbridge.c	\
+		util/virnetdevtap.h util/virnetdevtap.c
 
 EXTRA_DIST += $(srcdir)/util/virkeymaps.h $(srcdir)/util/keymaps.csv \
 		$(srcdir)/util/virkeycode-mapgen.py
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index c75941f..5701467 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -43,7 +43,7 @@
 #include "lxc_driver.h"
 #include "memory.h"
 #include "util.h"
-#include "bridge.h"
+#include "virnetdevbridge.h"
 #include "veth.h"
 #include "nodeinfo.h"
 #include "uuid.h"
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index bc9d2e1..bc3a18f 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -42,6 +42,7 @@
 #include <stdio.h>
 #include <sys/wait.h>
 #include <sys/ioctl.h>
+#include <net/if.h>
 
 #include "virterror_internal.h"
 #include "datatypes.h"
@@ -55,13 +56,15 @@
 #include "memory.h"
 #include "uuid.h"
 #include "iptables.h"
-#include "bridge.h"
 #include "interface.h"
 #include "logging.h"
 #include "dnsmasq.h"
 #include "util/network.h"
 #include "configmake.h"
 #include "ignore-value.h"
+#include "virnetdev.h"
+#include "virnetdevbridge.h"
+#include "virnetdevtap.h"
 
 #define NETWORK_PID_DIR LOCALSTATEDIR "/run/libvirt/network"
 #define NETWORK_STATE_DIR LOCALSTATEDIR "/lib/libvirt/network"
diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c
index 69ff444..12867d3 100644
--- a/src/openvz/openvz_driver.c
+++ b/src/openvz/openvz_driver.c
@@ -54,7 +54,6 @@
 #include "openvz_conf.h"
 #include "nodeinfo.h"
 #include "memory.h"
-#include "bridge.h"
 #include "virfile.h"
 #include "logging.h"
 #include "command.h"
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 5680636..7c9e60b 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -38,6 +38,7 @@
 #include "domain_audit.h"
 #include "domain_conf.h"
 #include "network/bridge_driver.h"
+#include "virnetdevtap.h"
 
 #include <sys/utsname.h>
 #include <sys/stat.h>
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index 1ba2002..bbe7e74 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -28,7 +28,6 @@
 
 # include "ebtables.h"
 # include "internal.h"
-# include "bridge.h"
 # include "capabilities.h"
 # include "network_conf.h"
 # include "domain_conf.h"
diff --git a/src/uml/uml_conf.c b/src/uml/uml_conf.c
index 9b6abe7..3089abb 100644
--- a/src/uml/uml_conf.c
+++ b/src/uml/uml_conf.c
@@ -43,11 +43,11 @@
 #include "util.h"
 #include "memory.h"
 #include "nodeinfo.h"
-#include "bridge.h"
 #include "logging.h"
 #include "domain_nwfilter.h"
 #include "virfile.h"
 #include "command.h"
+#include "virnetdevtap.h"
 
 #define VIR_FROM_THIS VIR_FROM_UML
 
diff --git a/src/uml/uml_conf.h b/src/uml/uml_conf.h
index 01695c7..383ae66 100644
--- a/src/uml/uml_conf.h
+++ b/src/uml/uml_conf.h
@@ -25,7 +25,6 @@
 # define __UML_CONF_H
 
 # include "internal.h"
-# include "bridge.h"
 # include "capabilities.h"
 # include "network_conf.h"
 # include "domain_conf.h"
diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c
index 4a417ab..c5587d0 100644
--- a/src/uml/uml_driver.c
+++ b/src/uml/uml_driver.c
@@ -62,6 +62,7 @@
 #include "virfile.h"
 #include "fdstream.h"
 #include "configmake.h"
+#include "virnetdevtap.h"
 
 #define VIR_FROM_THIS VIR_FROM_UML
 
diff --git a/src/util/bridge.c b/src/util/bridge.c
deleted file mode 100644
index 0265e81..0000000
--- a/src/util/bridge.c
+++ /dev/null
@@ -1,1115 +0,0 @@
-/*
- * Copyright (C) 2007, 2009, 2011 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
- *
- * Authors:
- *     Mark McLoughlin <markmc at redhat.com>
- */
-
-#include <config.h>
-
-#if defined(WITH_BRIDGE)
-
-# include "bridge.h"
-# include "virfile.h"
-
-# include <stdlib.h>
-# include <stdio.h>
-# include <string.h>
-# include <unistd.h>
-# include <fcntl.h>
-# include <errno.h>
-# include <arpa/inet.h>
-# include <sys/types.h>
-# include <sys/socket.h>
-# include <sys/ioctl.h>
-# include <paths.h>
-# include <sys/wait.h>
-
-# include <linux/param.h>     /* HZ                 */
-# include <linux/sockios.h>   /* SIOCBRADDBR etc.   */
-# include <linux/if_bridge.h> /* SYSFS_BRIDGE_ATTR  */
-# include <linux/if_tun.h>    /* IFF_TUN, IFF_NO_PI */
-# include <net/if_arp.h>    /* ARPHRD_ETHER */
-
-# include "internal.h"
-# include "command.h"
-# include "memory.h"
-# include "util.h"
-# include "logging.h"
-# include "network.h"
-# include "virterror_internal.h"
-# include "intprops.h"
-
-# define JIFFIES_TO_MS(j) (((j)*1000)/HZ)
-# define MS_TO_JIFFIES(ms) (((ms)*HZ)/1000)
-
-# define VIR_FROM_THIS VIR_FROM_NONE
-
-static int virNetDevSetupControlFull(const char *ifname,
-                                     struct ifreq *ifr,
-                                     int domain,
-                                     int type)
-{
-    int fd;
-
-    if (ifname && ifr) {
-        memset(ifr, 0, sizeof(*ifr));
-
-        if (virStrcpyStatic(ifr->ifr_name, ifname) == NULL) {
-            virReportSystemError(ERANGE,
-                                 _("Network interface name '%s' is too long"),
-                                 ifname);
-            return -1;
-        }
-    }
-
-    if ((fd = socket(domain, type, 0)) < 0) {
-        virReportSystemError(errno, "%s",
-                             _("Cannot open network interface control socket"));
-        return -1;
-    }
-
-    if (virSetInherit(fd, false) < 0) {
-        virReportSystemError(errno, "%s",
-                             _("Cannot set close-on-exec flag for socket"));
-        VIR_FORCE_CLOSE(fd);
-        return -1;
-    }
-
-    return fd;
-}
-
-
-static int virNetDevSetupControl(const char *ifname,
-                                 struct ifreq *ifr)
-{
-    return virNetDevSetupControlFull(ifname, ifr, AF_PACKET, SOCK_DGRAM);
-}
-
-# define SYSFS_NET_DIR "/sys/class/net"
-/*
- * Bridge parameters can be set via sysfs on newish kernels,
- * or by  ioctl on older kernels. Perhaps we could just use
- * ioctl for every kernel, but its not clear what the long
- * term lifespan of the ioctl interface is...
- */
-static int virNetDevBridgeSet(const char *brname,
-                              const char *paramname,  /* sysfs param name */
-                              unsigned long value,    /* new value */
-                              int fd,                 /* control socket */
-                              struct ifreq *ifr)      /* pre-filled bridge name */
-{
-    char *path = NULL;
-    int ret = -1;
-
-    if (virAsprintf(&path, "%s/%s/bridge/%s", SYSFS_NET_DIR, brname, paramname) < 0) {
-        virReportOOMError();
-        return -1;
-    }
-
-    if (virFileExists(path)) {
-        char valuestr[INT_BUFSIZE_BOUND(value)];
-        snprintf(valuestr, sizeof(valuestr), "%lu", value);
-        if (virFileWriteStr(path, valuestr, 0) < 0) {
-            virReportSystemError(errno,
-                                 _("Unable to set bridge %s %s"), brname, paramname);
-            goto cleanup;
-        }
-    } else {
-        unsigned long paramid;
-        if (STREQ(paramname, "stp_state")) {
-            paramid = BRCTL_SET_BRIDGE_STP_STATE;
-        } else if (STREQ(paramname, "forward_delay")) {
-            paramid = BRCTL_SET_BRIDGE_FORWARD_DELAY;
-        } else {
-            virReportSystemError(EINVAL,
-                                 _("Unable to set bridge %s %s"), brname, paramname);
-            goto cleanup;
-        }
-        unsigned long args[] = { paramid, value, 0, 0 };
-        ifr->ifr_data = (char*)&args;
-        if (ioctl(fd, SIOCDEVPRIVATE, ifr) < 0) {
-            virReportSystemError(errno,
-                                 _("Unable to set bridge %s %s"), brname, paramname);
-            goto cleanup;
-        }
-    }
-
-    ret = 0;
-cleanup:
-    VIR_FREE(path);
-    return ret;
-}
-
-
-static int virNetDevBridgeGet(const char *brname,
-                              const char *paramname,  /* sysfs param name */
-                              unsigned long *value,   /* current value */
-                              int fd,                 /* control socket */
-                              struct ifreq *ifr)      /* pre-filled bridge name */
-{
-    char *path = NULL;
-    int ret = -1;
-
-    if (virAsprintf(&path, "%s/%s/bridge/%s", SYSFS_NET_DIR, brname, paramname) < 0) {
-        virReportOOMError();
-        return -1;
-    }
-
-    if (virFileExists(path)) {
-        char *valuestr;
-        if (virFileReadAll(path, INT_BUFSIZE_BOUND(unsigned long), &valuestr) < 0)
-            goto cleanup;
-
-        if (virStrToLong_ul(valuestr, NULL, 10, value) < 0) {
-            virReportSystemError(EINVAL,
-                                 _("Unable to get bridge %s %s"), brname, paramname);
-        }
-    } else {
-        struct __bridge_info info;
-        unsigned long args[] = { BRCTL_GET_BRIDGE_INFO, (unsigned long)&info, 0, 0 };
-        ifr->ifr_data = (char*)&args;
-        if (ioctl(fd, SIOCDEVPRIVATE, ifr) < 0) {
-            virReportSystemError(errno,
-                                 _("Unable to get bridge %s %s"), brname, paramname);
-            goto cleanup;
-        }
-
-        if (STREQ(paramname, "stp_state")) {
-            *value = info.stp_enabled;
-        } else if (STREQ(paramname, "forward_delay")) {
-            *value = info.forward_delay;
-        } else {
-            virReportSystemError(EINVAL,
-                                 _("Unable to get bridge %s %s"), brname, paramname);
-            goto cleanup;
-        }
-    }
-
-    ret = 0;
-cleanup:
-    VIR_FREE(path);
-    return ret;
-}
-
-
-/**
- * virNetDevBridgeCreate:
- * @brname: the bridge name
- *
- * This function register a new bridge
- *
- * Returns 0 in case of success or -1 on failure
- */
-# ifdef SIOCBRADDBR
-int virNetDevBridgeCreate(const char *brname)
-{
-    int fd = -1;
-    int ret = -1;
-
-    if ((fd = virNetDevSetupControl(NULL, NULL)) < 0)
-        return -1;
-
-    if (ioctl(fd, SIOCBRADDBR, brname) < 0) {
-        virReportSystemError(errno,
-                             _("Unable to create bridge %s"), brname);
-        goto cleanup;
-    }
-
-    ret = 0;
-
-cleanup:
-    VIR_FORCE_CLOSE(fd);
-    return ret;
-}
-# else
-int virNetDevBridgeCreate(const char *brname)
-{
-    virReportSystemError(ENOSYS,
-                         _("Unable to create bridge %s"), brname);
-    return -1;
-}
-# endif
-
-# ifdef SIOCBRDELBR
-/**
- * virNetDevExists:
- * @ifname
- *
- * Check if the network device @ifname exists
- *
- * Returns 1 if it exists, 0 if it does not, -1 on error
- */
-int virNetDevExists(const char *ifname)
-{
-    int fd = -1;
-    int ret = -1;
-    struct ifreq ifr;
-
-    if ((fd = virNetDevSetupControl(ifname, &ifr)) < 0)
-        return -1;
-
-    if (ioctl(fd, SIOCGIFFLAGS, &ifr)) {
-        if (errno == ENODEV)
-            ret = 0;
-        else
-            virReportSystemError(errno,
-                                 _("Unable to check interface flags for %s"), ifname);
-        goto cleanup;
-    }
-
-    ret = 1;
-
-cleanup:
-    VIR_FORCE_CLOSE(fd);
-    return ret;
-}
-# else
-int virNetDevExists(const char *ifname)
-{
-    virReportSystemError(errno,
-                         _("Unable to check interface %s"), ifname);
-    return -1;
-}
-# endif
-
-/**
- * virNetDevBridgeDelete:
- * @brname: the bridge name
- *
- * Remove a bridge from the layer.
- *
- * Returns 0 in case of success or an errno code in case of failure.
- */
-# ifdef SIOCBRDELBR
-int virNetDevBridgeDelete(const char *brname)
-{
-    int fd = -1;
-    int ret = -1;
-
-    if ((fd = virNetDevSetupControl(NULL, NULL)) < 0)
-        return -1;
-
-    if (ioctl(fd, SIOCBRDELBR, brname) < 0) {
-        virReportSystemError(errno,
-                             _("Unable to delete bridge %s"), brname);
-        goto cleanup;
-    }
-
-    ret = 0;
-
-cleanup:
-    VIR_FORCE_CLOSE(fd);
-    return ret;
-}
-# else
-int virNetDevBridgeDelete(const char *brname ATTRIBUTE_UNUSED)
-{
-    virReportSystemError(errno,
-                         _("Unable to delete bridge %s"), brname);
-    return EINVAL;
-}
-# endif
-
-/**
- * virNetDevBridgeAddPort:
- * @brname: the bridge name
- * @ifname: the network interface name
- *
- * Adds an interface to a bridge
- *
- * Returns 0 in case of success or an errno code in case of failure.
- */
-# ifdef SIOCBRADDIF
-int virNetDevBridgeAddPort(const char *brname,
-                           const char *ifname)
-{
-    int fd = -1;
-    int ret = -1;
-    struct ifreq ifr;
-
-    if ((fd = virNetDevSetupControl(brname, &ifr)) < 0)
-        return -1;
-
-    if (!(ifr.ifr_ifindex = if_nametoindex(ifname))) {
-        virReportSystemError(errno,
-                             _("Unable to get interface index for %s"), ifname);
-        goto cleanup;
-    }
-
-    if (ioctl(fd, SIOCBRADDIF, &ifr) < 0) {
-        virReportSystemError(errno,
-                             _("Unable to add bridge %s port %s"), brname, ifname);
-        goto cleanup;
-    }
-
-    ret = 0;
-cleanup:
-    VIR_FORCE_CLOSE(fd);
-    return ret;
-}
-# else
-int virNetDevBridgeAddPort(const char *brname,
-                           const char *ifname)
-{
-    virReportSystemError(ENOSYS,
-                         _("Unable to add bridge %s port %s"), brname, ifname);
-    return -1;
-}
-# endif
-
-/**
- * virNetDevBridgeRemovePort:
- * @brname: the bridge name
- * @ifname: the network interface name
- *
- * Removes an interface from a bridge
- *
- * Returns 0 in case of success or an errno code in case of failure.
- */
-# ifdef SIOCBRDELIF
-int virNetDevBridgeRemovePort(const char *brname,
-                              const char *ifname)
-{
-    int fd = -1;
-    int ret = -1;
-    struct ifreq ifr;
-
-    if ((fd = virNetDevSetupControl(brname, &ifr)) < 0)
-        return -1;
-
-    if (!(ifr.ifr_ifindex = if_nametoindex(ifname))) {
-        virReportSystemError(errno,
-                             _("Unable to get interface index for %s"), ifname);
-
-        goto cleanup;
-    }
-
-    if (ioctl(fd, SIOCBRDELIF, &ifr) < 0) {
-        virReportSystemError(errno,
-                             _("Unable to remove bridge %s port %s"), brname, ifname);
-        goto cleanup;
-    }
-
-    ret = 0;
-cleanup:
-    VIR_FORCE_CLOSE(fd);
-    return ret;
-}
-# else
-int virNetDevBridgeRemovePort(const char *brname,
-                              const char *ifname)
-{
-    virReportSystemError(errno,
-                         _("Unable to remove bridge %s port %s"), brname, ifname);
-    return -1;
-}
-# endif
-
-/**
- * virNetDevSetMAC:
- * @ifname: interface name to set MTU for
- * @macaddr: MAC address (VIR_MAC_BUFLEN in size)
- *
- * This function sets the @macaddr for a given interface @ifname. This
- * gets rid of the kernel's automatically assigned random MAC.
- *
- * Returns 0 in case of success or -1 on failure
- */
-int virNetDevSetMAC(const char *ifname,
-                    const unsigned char *macaddr)
-{
-    int fd = -1;
-    int ret = -1;
-    struct ifreq ifr;
-
-    if ((fd = virNetDevSetupControl(ifname, &ifr)) < 0)
-        return -1;
-
-    /* To fill ifr.ifr_hdaddr.sa_family field */
-    if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) {
-        virReportSystemError(errno,
-                             _("Cannot get interface MAC on '%s'"),
-                             ifname);
-        goto cleanup;
-    }
-
-    memcpy(ifr.ifr_hwaddr.sa_data, macaddr, VIR_MAC_BUFLEN);
-
-    if (ioctl(fd, SIOCSIFHWADDR, &ifr) < 0) {
-        virReportSystemError(errno,
-                             _("Cannot set interface MAC on '%s'"),
-                             ifname);
-        goto cleanup;
-    }
-
-    ret = 0;
-
-cleanup:
-    VIR_FORCE_CLOSE(fd);
-    return ret;
-}
-
-/**
- * virNetDevGetMAC:
- * @ifname: interface name to set MTU for
- * @macaddr: MAC address (VIR_MAC_BUFLEN in size)
- *
- * This function gets the @macaddr for a given interface @ifname.
- *
- * Returns 0 in case of success or -1 on failure
- */
-int virNetDevGetMAC(const char *ifname,
-                    unsigned char *macaddr)
-{
-    int fd = -1;
-    int ret = -1;
-    struct ifreq ifr;
-
-    if ((fd = virNetDevSetupControl(ifname, &ifr)) < 0)
-        return -1;
-
-    if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) {
-        virReportSystemError(errno,
-                             _("Cannot get interface MAC on '%s'"),
-                             ifname);
-        goto cleanup;
-    }
-
-    memcpy(macaddr, ifr.ifr_hwaddr.sa_data, VIR_MAC_BUFLEN);
-
-    ret = 0;
-
-cleanup:
-    VIR_FORCE_CLOSE(fd);
-    return ret;
-}
-
-/**
- * virNetDevGetMTU:
- * @ifname: interface name get MTU for
- *
- * This function gets the @mtu value set for a given interface @ifname.
- *
- * Returns the MTU value in case of success, or -1 on failure.
- */
-int virNetDevGetMTU(const char *ifname)
-{
-    int fd = -1;
-    int ret = -1;
-    struct ifreq ifr;
-
-    if ((fd = virNetDevSetupControl(ifname, &ifr)) < 0)
-        return -1;
-
-    if (ioctl(fd, SIOCGIFMTU, &ifr) < 0) {
-        virReportSystemError(errno,
-                             _("Cannot get interface MTU on '%s'"),
-                             ifname);
-        goto cleanup;
-    }
-
-    ret = ifr.ifr_mtu;
-
-cleanup:
-    VIR_FORCE_CLOSE(fd);
-    return ret;
-}
-
-/**
- * virNetDevSetMTU:
- * @ifname: interface name to set MTU for
- * @mtu: MTU value
- *
- * This function sets the @mtu for a given interface @ifname.  Typically
- * used on a tap device to set up for Jumbo Frames.
- *
- * Returns 0 in case of success, or -1 on failure
- */
-int virNetDevSetMTU(const char *ifname, int mtu)
-{
-    int fd = -1;
-    int ret = -1;
-    struct ifreq ifr;
-
-    if ((fd = virNetDevSetupControl(ifname, &ifr)) < 0)
-        return -1;
-
-    ifr.ifr_mtu = mtu;
-
-    if (ioctl(fd, SIOCSIFMTU, &ifr) < 0) {
-        virReportSystemError(errno,
-                             _("Cannot set interface MTU on '%s'"),
-                             ifname);
-        goto cleanup;
-    }
-
-    ret = 0;
-
-cleanup:
-    VIR_FORCE_CLOSE(fd);
-    return ret;
-}
-
-/**
- * virNetDevSetMTUFromDevice:
- * @ifname: name of the interface whose MTU we want to set
- * @otherifname: name of the interface whose MTU we want to copy
- *
- * Sets the interface mtu to the same MTU as another interface
- *
- * Returns 0 in case of success, or -1 on failure
- */
-int virNetDevSetMTUFromDevice(const char *ifname,
-                              const char *otherifname)
-{
-    int mtu = virNetDevGetMTU(otherifname);
-
-    if (mtu < 0)
-        return -1;
-
-    return virNetDevSetMTU(ifname, mtu);
-}
-
-/**
- * virNetDevProbeVnetHdr:
- * @tapfd: a tun/tap file descriptor
- *
- * Check whether it is safe to enable the IFF_VNET_HDR flag on the
- * tap interface.
- *
- * Setting IFF_VNET_HDR enables QEMU's virtio_net driver to allow
- * guests to pass larger (GSO) packets, with partial checksums, to
- * the host. This greatly increases the achievable throughput.
- *
- * It is only useful to enable this when we're setting up a virtio
- * interface. And it is only *safe* to enable it when we know for
- * sure that a) qemu has support for IFF_VNET_HDR and b) the running
- * kernel implements the TUNGETIFF ioctl(), which qemu needs to query
- * the supplied tapfd.
- *
- * Returns 1 if VnetHdr is supported, 0 if not supported
- */
-# ifdef IFF_VNET_HDR
-static int
-virNetDevProbeVnetHdr(int tapfd)
-{
-#  if defined(IFF_VNET_HDR) && defined(TUNGETFEATURES) && defined(TUNGETIFF)
-    unsigned int features;
-    struct ifreq dummy;
-
-    if (ioctl(tapfd, TUNGETFEATURES, &features) != 0) {
-        VIR_INFO("Not enabling IFF_VNET_HDR; "
-                 "TUNGETFEATURES ioctl() not implemented");
-        return 0;
-    }
-
-    if (!(features & IFF_VNET_HDR)) {
-        VIR_INFO("Not enabling IFF_VNET_HDR; "
-                 "TUNGETFEATURES ioctl() reports no IFF_VNET_HDR");
-        return 0;
-    }
-
-    /* The kernel will always return -1 at this point.
-     * If TUNGETIFF is not implemented then errno == EBADFD.
-     */
-    if (ioctl(tapfd, TUNGETIFF, &dummy) != -1 || errno != EBADFD) {
-        VIR_INFO("Not enabling IFF_VNET_HDR; "
-                 "TUNGETIFF ioctl() not implemented");
-        return 0;
-    }
-
-    VIR_INFO("Enabling IFF_VNET_HDR");
-
-    return 1;
-#  else
-    (void) tapfd;
-    VIR_INFO("Not enabling IFF_VNET_HDR; disabled at build time");
-    return 0;
-#  endif
-}
-# endif
-
-/**
- * brAddTap:
- * @brname: the bridge name
- * @ifname: the interface name (or name template)
- * @macaddr: desired MAC address (VIR_MAC_BUFLEN long)
- * @vnet_hdr: whether to try enabling IFF_VNET_HDR
- * @tapfd: file descriptor return value for the new tap device
- *
- * This function creates a new tap device on a bridge. @ifname can be either
- * a fixed name or a name template with '%d' for dynamic name allocation.
- * in either case the final name for the bridge will be stored in @ifname.
- * If the @tapfd parameter is supplied, the open tap device file
- * descriptor will be returned, otherwise the TAP device will be made
- * persistent and closed. The caller must use brDeleteTap to remove
- * a persistent TAP devices when it is no longer needed.
- *
- * Returns 0 in case of success or -1 on failure
- */
-int virNetDevTapCreateInBridgePort(const char *brname,
-                                   char **ifname,
-                                   const unsigned char *macaddr,
-                                   int vnet_hdr,
-                                   bool up,
-                                   int *tapfd)
-{
-    if (virNetDevTapCreate(ifname, vnet_hdr, tapfd) < 0)
-        return -1;
-
-    /* We need to set the interface MAC before adding it
-     * to the bridge, because the bridge assumes the lowest
-     * MAC of all enslaved interfaces & we don't want it
-     * seeing the kernel allocate random MAC for the TAP
-     * device before we set our static MAC.
-     */
-    if (virNetDevSetMAC(*ifname, macaddr) < 0)
-        goto error;
-
-    /* We need to set the interface MTU before adding it
-     * to the bridge, because the bridge will have its
-     * MTU adjusted automatically when we add the new interface.
-     */
-    if (virNetDevSetMTUFromDevice(*ifname, brname) < 0)
-        goto error;
-
-    if (virNetDevBridgeAddPort(brname, *ifname) < 0)
-        goto error;
-
-    if (virNetDevSetOnline(*ifname, up) < 0)
-        goto error;
-
-    return 0;
-
-error:
-    if (tapfd)
-        VIR_FORCE_CLOSE(*tapfd);
-    return -1;
-}
-
-int virNetDevTapDelete(const char *ifname)
-{
-    struct ifreq try;
-    int fd;
-    int ret = -1;
-
-    if ((fd = open("/dev/net/tun", O_RDWR)) < 0) {
-        virReportSystemError(errno, "%s",
-                             _("Unable to open /dev/net/tun, is tun module loaded?"));
-        return -1;
-    }
-
-    memset(&try, 0, sizeof(struct ifreq));
-    try.ifr_flags = IFF_TAP|IFF_NO_PI;
-
-    if (virStrcpyStatic(try.ifr_name, ifname) == NULL) {
-        virReportSystemError(ERANGE,
-                             _("Network interface name '%s' is too long"),
-                             ifname);
-        goto cleanup;
-    }
-
-    if (ioctl(fd, TUNSETIFF, &try) < 0) {
-        virReportSystemError(errno, "%s",
-                             _("Unable to associate TAP device"));
-        goto cleanup;
-    }
-
-    if (ioctl(fd, TUNSETPERSIST, 0) < 0) {
-        virReportSystemError(errno, "%s",
-                             _("Unable to make TAP device non-persistent"));
-        goto cleanup;
-    }
-
-    ret = 0;
-
-cleanup:
-    VIR_FORCE_CLOSE(fd);
-    return ret;
-}
-
-
-/**
- * virNetDevSetOnline:
- * @ifname: the interface name
- * @online: true for up, false for down
- *
- * Function to control if an interface is activated (up, true) or not (down, false)
- *
- * Returns 0 in case of success or -1 on error.
- */
-int virNetDevSetOnline(const char *ifname,
-                       bool online)
-{
-    int fd = -1;
-    int ret = -1;
-    struct ifreq ifr;
-    int ifflags;
-
-    if ((fd = virNetDevSetupControl(ifname, &ifr)) < 0)
-        return -1;
-
-    if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
-        virReportSystemError(errno,
-                             _("Cannot get interface flags on '%s'"),
-                             ifname);
-        goto cleanup;
-    }
-
-    if (online)
-        ifflags = ifr.ifr_flags | IFF_UP;
-    else
-        ifflags = ifr.ifr_flags & ~IFF_UP;
-
-    if (ifr.ifr_flags != ifflags) {
-        ifr.ifr_flags = ifflags;
-        if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) {
-            virReportSystemError(errno,
-                                 _("Cannot set interface flags on '%s'"),
-                                 ifname);
-            goto cleanup;
-        }
-    }
-
-    ret = 0;
-
-cleanup:
-    VIR_FORCE_CLOSE(fd);
-    return ret;
-}
-
-/**
- * virNetDevIsOnline:
- * @ifname: the interface name
- * @online: where to store the status
- *
- * Function to query if an interface is activated (true) or not (false)
- *
- * Returns 0 in case of success or an errno code in case of failure.
- */
-int virNetDevIsOnline(const char *ifname,
-                      bool *online)
-{
-    int fd = -1;
-    int ret = -1;
-    struct ifreq ifr;
-
-    if ((fd = virNetDevSetupControl(ifname, &ifr)) < 0)
-        return -1;
-
-    if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
-        virReportSystemError(errno,
-                             _("Cannot get interface flags on '%s'"),
-                             ifname);
-        goto cleanup;
-    }
-
-    *online = (ifr.ifr_flags & IFF_UP) ? true : false;
-    ret = 0;
-
-cleanup:
-    VIR_FORCE_CLOSE(fd);
-    return ret;
-}
-
-/**
- * virNetDevSetIPv4Addres:
- * @ifname: the interface name
- * @addr: the IP address (IPv4 or IPv6)
- * @prefix: number of 1 bits in the netmask
- *
- * Add an IP address to an interface. This function *does not* remove
- * any previously added IP addresses - that must be done separately with
- * brDelInetAddress.
- *
- * Returns 0 in case of success or -1 in case of error.
- */
-
-int virNetDevSetIPv4Addres(const char *ifname,
-                           virSocketAddr *addr,
-                           unsigned int prefix)
-{
-    virCommandPtr cmd = NULL;
-    char *addrstr = NULL, *bcaststr = NULL;
-    virSocketAddr broadcast;
-    int ret = -1;
-
-    if (!(addrstr = virSocketFormatAddr(addr)))
-        goto cleanup;
-    /* format up a broadcast address if this is IPv4 */
-    if ((VIR_SOCKET_IS_FAMILY(addr, AF_INET)) &&
-        ((virSocketAddrBroadcastByPrefix(addr, prefix, &broadcast) < 0) ||
-         !(bcaststr = virSocketFormatAddr(&broadcast)))) {
-        goto cleanup;
-    }
-    cmd = virCommandNew(IP_PATH);
-    virCommandAddArgList(cmd, "addr", "add", NULL);
-    virCommandAddArgFormat(cmd, "%s/%u", addrstr, prefix);
-    if (bcaststr)
-        virCommandAddArgList(cmd, "broadcast", bcaststr, NULL);
-    virCommandAddArgList(cmd, "dev", ifname, NULL);
-
-    if (virCommandRun(cmd, NULL) < 0)
-        goto cleanup;
-
-    ret = 0;
-cleanup:
-    VIR_FREE(addrstr);
-    VIR_FREE(bcaststr);
-    virCommandFree(cmd);
-    return ret;
-}
-
-/**
- * virNetDevClearIPv4Address:
- * @ifname: the interface name
- * @addr: the IP address (IPv4 or IPv6)
- * @prefix: number of 1 bits in the netmask
- *
- * Delete an IP address from an interface.
- *
- * Returns 0 in case of success or -1 in case of error.
- */
-
-int virNetDevClearIPv4Address(const char *ifname,
-                              virSocketAddr *addr,
-                              unsigned int prefix)
-{
-    virCommandPtr cmd = NULL;
-    char *addrstr;
-    int ret = -1;
-
-    if (!(addrstr = virSocketFormatAddr(addr)))
-        goto cleanup;
-    cmd = virCommandNew(IP_PATH);
-    virCommandAddArgList(cmd, "addr", "del", NULL);
-    virCommandAddArgFormat(cmd, "%s/%u", addrstr, prefix);
-    virCommandAddArgList(cmd, "dev", ifname, NULL);
-
-    if (virCommandRun(cmd, NULL) < 0)
-        goto cleanup;
-
-    ret = 0;
-cleanup:
-    VIR_FREE(addrstr);
-    virCommandFree(cmd);
-    return ret;
-}
-
-/**
- * virNetDevBridgeSetSTPDelay:
- * @brname: the bridge name
- * @delay: delay in seconds
- *
- * Set the bridge forward delay
- *
- * Returns 0 in case of success or -1 on failure
- */
-
-int virNetDevBridgeSetSTPDelay(const char *brname,
-                               int delay)
-{
-    int fd = -1;
-    int ret = -1;
-    struct ifreq ifr;
-
-    if ((fd = virNetDevSetupControl(brname, &ifr)) < 0)
-        goto cleanup;
-
-    ret = virNetDevBridgeSet(brname, "stp_state", MS_TO_JIFFIES(delay),
-                             fd, &ifr);
-
-cleanup:
-    VIR_FORCE_CLOSE(fd);
-    return ret;
-}
-
-
-/**
- * virNetDevBridgeGetSTPDelay:
- * @brname: the bridge device name
- * @delayms: the forward delay in milliseconds
- *
- * Retrives the forward delay for the bridge device @brname
- * storing it in @delayms. The forward delay is only meaningful
- * if STP is enabled
- *
- * Returns 0 on success, -1 on error+
- */
-int virNetDevBridgeGetSTPDelay(const char *brname,
-                               int *delayms)
-{
-    int fd = -1;
-    int ret = -1;
-    struct ifreq ifr;
-    unsigned long i;
-
-    if ((fd = virNetDevSetupControl(brname, &ifr)) < 0)
-        goto cleanup;
-
-    ret = virNetDevBridgeGet(brname, "stp_state", &i,
-                             fd, &ifr);
-    *delayms = JIFFIES_TO_MS(i);
-
-cleanup:
-    VIR_FORCE_CLOSE(fd);
-    return ret;
-}
-
-
-/**
- * virNetDevBridgeSetSTP:
- * @brname: the bridge name
- * @enable: 1 to enable, 0 to disable
- *
- * Control whether the bridge participates in the spanning tree protocol,
- * in general don't disable it without good reasons.
- *
- * Returns 0 in case of success or -1 on failure
- */
-int virNetDevBridgeSetSTP(const char *brname,
-                          bool enable)
-{
-    int fd = -1;
-    int ret = -1;
-    struct ifreq ifr;
-
-    if ((fd = virNetDevSetupControl(brname, &ifr)) < 0)
-        goto cleanup;
-
-    ret = virNetDevBridgeSet(brname, "stp_state", enable ? 1 : 0,
-                             fd, &ifr);
-
-cleanup:
-    VIR_FORCE_CLOSE(fd);
-    return ret;
-}
-
-
-/**
- * virNetDevBridgeGetSTP:
- * @brname: the bridge device name
- * @enabled: returns the STP state
- *
- * Determine the state of the spanning tree protocol on
- * the device @brname, returning the state in @enabled
- *
- * Returns 0 on success, -1 on error
- */
-int virNetDevBridgeGetSTP(const char *brname,
-                          bool *enabled)
-{
-    int fd = -1;
-    int ret = -1;
-    struct ifreq ifr;
-    unsigned long i;
-
-    if ((fd = virNetDevSetupControl(brname, &ifr)) < 0)
-        goto cleanup;
-
-    ret = virNetDevBridgeGet(brname, "stp_state", &i,
-                             fd, &ifr);
-    *enabled = i ? true : false;
-
-cleanup:
-    VIR_FORCE_CLOSE(fd);
-    return ret;
-}
-
-
-/**
- * brCreateTap:
- * @ifname: the interface name
- * @vnet_hr: whether to try enabling IFF_VNET_HDR
- * @tapfd: file descriptor return value for the new tap device
- *
- * Creates a tap interface.
- * If the @tapfd parameter is supplied, the open tap device file
- * descriptor will be returned, otherwise the TAP device will be made
- * persistent and closed. The caller must use brDeleteTap to remove
- * a persistent TAP devices when it is no longer needed.
- *
- * Returns 0 in case of success or an errno code in case of failure.
- */
-
-int virNetDevTapCreate(char **ifname,
-                       int vnet_hdr ATTRIBUTE_UNUSED,
-                       int *tapfd)
-{
-    int fd;
-    struct ifreq ifr;
-    int ret = -1;
-
-    if ((fd = open("/dev/net/tun", O_RDWR)) < 0) {
-        virReportSystemError(errno, "%s",
-                             _("Unable to open /dev/net/tun, is tun module loaded?"));
-        return -1;
-    }
-
-    memset(&ifr, 0, sizeof(ifr));
-
-    ifr.ifr_flags = IFF_TAP|IFF_NO_PI;
-
-# ifdef IFF_VNET_HDR
-    if (vnet_hdr && virNetDevProbeVnetHdr(fd))
-        ifr.ifr_flags |= IFF_VNET_HDR;
-# endif
-
-    if (virStrcpyStatic(ifr.ifr_name, *ifname) == NULL) {
-        virReportSystemError(ERANGE,
-                             _("Network interface name '%s' is too long"),
-                             *ifname);
-        goto cleanup;
-
-    }
-
-    if (ioctl(fd, TUNSETIFF, &ifr) < 0) {
-        virReportSystemError(errno,
-                             _("Unable to create tap device %s"),
-                             NULLSTR(*ifname));
-        goto cleanup;
-    }
-
-    if (!tapfd &&
-        (errno = ioctl(fd, TUNSETPERSIST, 1))) {
-        virReportSystemError(errno,
-                             _("Unable to set tap device %s to persistent"),
-                             NULLSTR(*ifname));
-        goto cleanup;
-    }
-
-    VIR_FREE(*ifname);
-    if (!(*ifname = strdup(ifr.ifr_name))) {
-        virReportOOMError();
-        goto cleanup;
-    }
-    if (tapfd)
-        *tapfd = fd;
-    else
-        VIR_FORCE_CLOSE(fd);
-
-    ret = 0;
-
-cleanup:
-    if (ret < 0)
-        VIR_FORCE_CLOSE(fd);
-
-    return ret;
-}
-
-#endif /* WITH_BRIDGE */
diff --git a/src/util/bridge.h b/src/util/bridge.h
deleted file mode 100644
index 7504925..0000000
--- a/src/util/bridge.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (C) 2007 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
- *
- * Authors:
- *     Mark McLoughlin <markmc at redhat.com>
- */
-
-#ifndef __QEMUD_BRIDGE_H__
-# define __QEMUD_BRIDGE_H__
-
-# include <config.h>
-
-# if defined(WITH_BRIDGE)
-
-#  include <net/if.h>
-#  include <netinet/in.h>
-#  include "network.h"
-
-/**
- * BR_IFNAME_MAXLEN:
- * maximum size in byte of the name for an interface
- */
-#  define BR_IFNAME_MAXLEN    IF_NAMESIZE
-
-/**
- * BR_INET_ADDR_MAXLEN:
- * maximum size in bytes for an inet addess name
- */
-#  define BR_INET_ADDR_MAXLEN INET_ADDRSTRLEN
-
-int virNetDevBridgeCreate(const char *brname)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
-int virNetDevBridgeDelete(const char *brname)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
-int virNetDevExists(const char *brname)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
-
-int virNetDevBridgeAddPort(const char *brname,
-                           const char *ifname)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
-
-int virNetDevBridgeRemovePort(const char *brname,
-                              const char *ifname)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
-
-enum {
-    BR_TAP_VNET_HDR = (1 << 0),
-    BR_TAP_PERSIST =  (1 << 1),
-};
-
-int virNetDevTapCreateInBridgePort(const char *brname,
-                                   char **ifname,
-                                   const unsigned char *macaddr,
-                                   int vnet_hdr,
-                                   bool up,
-                                   int *tapfd)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
-    ATTRIBUTE_RETURN_CHECK;
-
-
-int virNetDevTapDelete(const char *ifname)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
-
-int virNetDevSetOnline(const char *ifname,
-                       bool online)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
-int virNetDevIsOnline(const char *ifname,
-                      bool *online)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
-
-int virNetDevSetIPv4Addres(const char *ifname,
-                           virSocketAddr *addr,
-                           unsigned int prefix)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
-int virNetDevClearIPv4Address(const char *ifname,
-                              virSocketAddr *addr,
-                              unsigned int prefix)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
-
-int virNetDevBridgeSetSTPDelay(const char *brname,
-                               int delay)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
-int virNetDevBridgeGetSTPDelay(const char *brname,
-                               int *delay)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
-int virNetDevBridgeSetSTP(const char *brname,
-                          bool enable)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
-int virNetDevBridgeGetSTP(const char *brname,
-                          bool *enable)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
-
-int virNetDevTapCreate(char **ifname,
-                       int vnet_hdr,
-                       int *tapfd)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
-
-int virNetDevSetMAC(const char *ifname,
-                    const unsigned char *macaddr)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
-int virNetDevGetMAC(const char *ifname,
-                    unsigned char *macaddr)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
-int virNetDevSetMTU(const char *ifname,
-                    int mtu)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
-int virNetDevSetMTUFromDevice(const char *ifname,
-                              const char *otherifname)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
-int virNetDevGetMTU(const char *ifname)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
-
-# endif /* WITH_BRIDGE */
-
-#endif /* __QEMUD_BRIDGE_H__ */
diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c
new file mode 100644
index 0000000..6eb5fe7
--- /dev/null
+++ b/src/util/virnetdev.c
@@ -0,0 +1,524 @@
+/*
+ * Copyright (C) 2007-2011 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ * Authors:
+ *     Mark McLoughlin <markmc at redhat.com>
+ *     Daniel P. Berrange <berrange at redhat.com>
+ */
+
+#include <config.h>
+
+#include "virnetdev.h"
+#include "virfile.h"
+#include "virterror_internal.h"
+#include "command.h"
+#include "memory.h"
+
+#include <sys/ioctl.h>
+#ifdef HAVE_NET_IF_H
+# include <net/if.h>
+#endif
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+#ifdef HAVE_NET_IF_H
+static int virNetDevSetupControlFull(const char *ifname,
+                                     struct ifreq *ifr,
+                                     int domain,
+                                     int type)
+{
+    int fd;
+
+    memset(ifr, 0, sizeof(*ifr));
+
+    if (virStrcpyStatic(ifr->ifr_name, ifname) == NULL) {
+        virReportSystemError(ERANGE,
+                             _("Network interface name '%s' is too long"),
+                             ifname);
+        return -1;
+    }
+
+    if ((fd = socket(domain, type, 0)) < 0) {
+        virReportSystemError(errno, "%s",
+                             _("Cannot open network interface control socket"));
+        return -1;
+    }
+
+    if (virSetInherit(fd, false) < 0) {
+        virReportSystemError(errno, "%s",
+                             _("Cannot set close-on-exec flag for socket"));
+        VIR_FORCE_CLOSE(fd);
+        return -1;
+    }
+
+    return fd;
+}
+
+
+static int virNetDevSetupControl(const char *ifname,
+                                 struct ifreq *ifr)
+{
+    return virNetDevSetupControlFull(ifname, ifr, AF_PACKET, SOCK_DGRAM);
+}
+#endif
+
+
+#ifdef SIOCGIFFLAGS
+/**
+ * virNetDevExists:
+ * @ifname
+ *
+ * Check if the network device @ifname exists
+ *
+ * Returns 1 if it exists, 0 if it does not, -1 on error
+ */
+int virNetDevExists(const char *ifname)
+{
+    int fd = -1;
+    int ret = -1;
+    struct ifreq ifr;
+
+    if ((fd = virNetDevSetupControl(ifname, &ifr)) < 0)
+        return -1;
+
+    if (ioctl(fd, SIOCGIFFLAGS, &ifr)) {
+        if (errno == ENODEV)
+            ret = 0;
+        else
+            virReportSystemError(errno,
+                                 _("Unable to check interface flags for %s"), ifname);
+        goto cleanup;
+    }
+
+    ret = 1;
+
+cleanup:
+    VIR_FORCE_CLOSE(fd);
+    return ret;
+}
+#else
+int virNetDevExists(const char *ifname)
+{
+    virReportSystemError(errno,
+                         _("Unable to check interface %s"), ifname);
+    return -1;
+}
+#endif
+
+
+#ifdef SIOCGIFHWADDR
+/**
+ * virNetDevSetMAC:
+ * @ifname: interface name to set MTU for
+ * @macaddr: MAC address (VIR_MAC_BUFLEN in size)
+ *
+ * This function sets the @macaddr for a given interface @ifname. This
+ * gets rid of the kernel's automatically assigned random MAC.
+ *
+ * Returns 0 in case of success or -1 on failure
+ */
+int virNetDevSetMAC(const char *ifname,
+                    const unsigned char *macaddr)
+{
+    int fd = -1;
+    int ret = -1;
+    struct ifreq ifr;
+
+    if ((fd = virNetDevSetupControl(ifname, &ifr)) < 0)
+        return -1;
+
+    /* To fill ifr.ifr_hdaddr.sa_family field */
+    if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) {
+        virReportSystemError(errno,
+                             _("Cannot get interface MAC on '%s'"),
+                             ifname);
+        goto cleanup;
+    }
+
+    memcpy(ifr.ifr_hwaddr.sa_data, macaddr, VIR_MAC_BUFLEN);
+
+    if (ioctl(fd, SIOCSIFHWADDR, &ifr) < 0) {
+        virReportSystemError(errno,
+                             _("Cannot set interface MAC on '%s'"),
+                             ifname);
+        goto cleanup;
+    }
+
+    ret = 0;
+
+cleanup:
+    VIR_FORCE_CLOSE(fd);
+    return ret;
+}
+#else
+int virNetDevSetMAC(const char *ifname,
+                    const unsigned char *macaddr ATTRIBUTE_UNUSED)
+{
+    virReportSystemError(ENOSYS,
+                         _("Cannot set interface MAC on '%s'"),
+                         ifname);
+    return -1;
+}
+#endif
+
+
+#ifdef SIOCGIFHWADDR
+/**
+ * virNetDevGetMAC:
+ * @ifname: interface name to set MTU for
+ * @macaddr: MAC address (VIR_MAC_BUFLEN in size)
+ *
+ * This function gets the @macaddr for a given interface @ifname.
+ *
+ * Returns 0 in case of success or -1 on failure
+ */
+int virNetDevGetMAC(const char *ifname,
+                    unsigned char *macaddr)
+{
+    int fd = -1;
+    int ret = -1;
+    struct ifreq ifr;
+
+    if ((fd = virNetDevSetupControl(ifname, &ifr)) < 0)
+        return -1;
+
+    if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) {
+        virReportSystemError(errno,
+                             _("Cannot get interface MAC on '%s'"),
+                             ifname);
+        goto cleanup;
+    }
+
+    memcpy(macaddr, ifr.ifr_hwaddr.sa_data, VIR_MAC_BUFLEN);
+
+    ret = 0;
+
+cleanup:
+    VIR_FORCE_CLOSE(fd);
+    return ret;
+}
+#else
+int virNetDevGetMAC(const char *ifname,
+                    unsigned char *macaddr ATTRIBUTE_UNUSED)
+{
+    virReportSystemError(ENOSYS,
+                         _("Cannot get interface MAC on '%s'"),
+                         ifname);
+    return -1;
+}
+#endif
+
+
+#ifdef SIOCGIFMTU
+/**
+ * virNetDevGetMTU:
+ * @ifname: interface name get MTU for
+ *
+ * This function gets the @mtu value set for a given interface @ifname.
+ *
+ * Returns the MTU value in case of success, or -1 on failure.
+ */
+int virNetDevGetMTU(const char *ifname)
+{
+    int fd = -1;
+    int ret = -1;
+    struct ifreq ifr;
+
+    if ((fd = virNetDevSetupControl(ifname, &ifr)) < 0)
+        return -1;
+
+    if (ioctl(fd, SIOCGIFMTU, &ifr) < 0) {
+        virReportSystemError(errno,
+                             _("Cannot get interface MTU on '%s'"),
+                             ifname);
+        goto cleanup;
+    }
+
+    ret = ifr.ifr_mtu;
+
+cleanup:
+    VIR_FORCE_CLOSE(fd);
+    return ret;
+}
+#else
+int virNetDevGetMTU(const char *ifname)
+{
+    virReportSystemError(ENOSYS,
+                         _("Cannot get interface MTU on '%s'"),
+                         ifname);
+    return -1;
+}
+#endif
+
+
+#ifdef SIOCSIFMTU
+/**
+ * virNetDevSetMTU:
+ * @ifname: interface name to set MTU for
+ * @mtu: MTU value
+ *
+ * This function sets the @mtu for a given interface @ifname.  Typically
+ * used on a tap device to set up for Jumbo Frames.
+ *
+ * Returns 0 in case of success, or -1 on failure
+ */
+int virNetDevSetMTU(const char *ifname, int mtu)
+{
+    int fd = -1;
+    int ret = -1;
+    struct ifreq ifr;
+
+    if ((fd = virNetDevSetupControl(ifname, &ifr)) < 0)
+        return -1;
+
+    ifr.ifr_mtu = mtu;
+
+    if (ioctl(fd, SIOCSIFMTU, &ifr) < 0) {
+        virReportSystemError(errno,
+                             _("Cannot set interface MTU on '%s'"),
+                             ifname);
+        goto cleanup;
+    }
+
+    ret = 0;
+
+cleanup:
+    VIR_FORCE_CLOSE(fd);
+    return ret;
+}
+#else
+int virNetDevSetMTU(const char *ifname, int mtu ATTRIBUTE_UNUSED)
+{
+    virReportSystemError(ENOSYS,
+                         _("Cannot set interface MTU on '%s'"),
+                         ifname);
+    return -1;
+}
+#endif
+
+
+/**
+ * virNetDevSetMTUFromDevice:
+ * @ifname: name of the interface whose MTU we want to set
+ * @otherifname: name of the interface whose MTU we want to copy
+ *
+ * Sets the interface mtu to the same MTU as another interface
+ *
+ * Returns 0 in case of success, or -1 on failure
+ */
+int virNetDevSetMTUFromDevice(const char *ifname,
+                              const char *otherifname)
+{
+    int mtu = virNetDevGetMTU(otherifname);
+
+    if (mtu < 0)
+        return -1;
+
+    return virNetDevSetMTU(ifname, mtu);
+}
+
+
+#ifdef SIOCSIFFLAGS
+/**
+ * virNetDevSetOnline:
+ * @ifname: the interface name
+ * @online: true for up, false for down
+ *
+ * Function to control if an interface is activated (up, true) or not (down, false)
+ *
+ * Returns 0 in case of success or -1 on error.
+ */
+int virNetDevSetOnline(const char *ifname,
+                       bool online)
+{
+    int fd = -1;
+    int ret = -1;
+    struct ifreq ifr;
+    int ifflags;
+
+    if ((fd = virNetDevSetupControl(ifname, &ifr)) < 0)
+        return -1;
+
+    if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
+        virReportSystemError(errno,
+                             _("Cannot get interface flags on '%s'"),
+                             ifname);
+        goto cleanup;
+    }
+
+    if (online)
+        ifflags = ifr.ifr_flags | IFF_UP;
+    else
+        ifflags = ifr.ifr_flags & ~IFF_UP;
+
+    if (ifr.ifr_flags != ifflags) {
+        ifr.ifr_flags = ifflags;
+        if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) {
+            virReportSystemError(errno,
+                                 _("Cannot set interface flags on '%s'"),
+                                 ifname);
+            goto cleanup;
+        }
+    }
+
+    ret = 0;
+
+cleanup:
+    VIR_FORCE_CLOSE(fd);
+    return ret;
+}
+#else
+int virNetDevSetOnline(const char *ifname,
+                       bool online ATTRIBUTE_UNUSED)
+{
+    virReportSystemError(ENOSYS,
+                         _("Cannot set interface flags on '%s'"),
+                         ifname);
+    return -1;
+}
+#endif
+
+
+#ifdef SIOCGIFFLAGS
+/**
+ * virNetDevIsOnline:
+ * @ifname: the interface name
+ * @online: where to store the status
+ *
+ * Function to query if an interface is activated (true) or not (false)
+ *
+ * Returns 0 in case of success or an errno code in case of failure.
+ */
+int virNetDevIsOnline(const char *ifname,
+                      bool *online)
+{
+    int fd = -1;
+    int ret = -1;
+    struct ifreq ifr;
+
+    if ((fd = virNetDevSetupControl(ifname, &ifr)) < 0)
+        return -1;
+
+    if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
+        virReportSystemError(errno,
+                             _("Cannot get interface flags on '%s'"),
+                             ifname);
+        goto cleanup;
+    }
+
+    *online = (ifr.ifr_flags & IFF_UP) ? true : false;
+    ret = 0;
+
+cleanup:
+    VIR_FORCE_CLOSE(fd);
+    return ret;
+}
+#else
+int virNetDevIsOnline(const char *ifname,
+                      bool *online ATTRIBUTE_UNUSED)
+{
+    virReportSystemError(ENOSYS,
+                         _("Cannot get interface flags on '%s'"),
+                         ifname);
+    return -1;
+}
+#endif
+
+
+/**
+ * virNetDevSetIPv4Addres:
+ * @ifname: the interface name
+ * @addr: the IP address (IPv4 or IPv6)
+ * @prefix: number of 1 bits in the netmask
+ *
+ * Add an IP address to an interface. This function *does not* remove
+ * any previously added IP addresses - that must be done separately with
+ * brDelInetAddress.
+ *
+ * Returns 0 in case of success or -1 in case of error.
+ */
+
+int virNetDevSetIPv4Addres(const char *ifname,
+                           virSocketAddr *addr,
+                           unsigned int prefix)
+{
+    virCommandPtr cmd = NULL;
+    char *addrstr = NULL, *bcaststr = NULL;
+    virSocketAddr broadcast;
+    int ret = -1;
+
+    if (!(addrstr = virSocketFormatAddr(addr)))
+        goto cleanup;
+    /* format up a broadcast address if this is IPv4 */
+    if ((VIR_SOCKET_IS_FAMILY(addr, AF_INET)) &&
+        ((virSocketAddrBroadcastByPrefix(addr, prefix, &broadcast) < 0) ||
+         !(bcaststr = virSocketFormatAddr(&broadcast)))) {
+        goto cleanup;
+    }
+    cmd = virCommandNew(IP_PATH);
+    virCommandAddArgList(cmd, "addr", "add", NULL);
+    virCommandAddArgFormat(cmd, "%s/%u", addrstr, prefix);
+    if (bcaststr)
+        virCommandAddArgList(cmd, "broadcast", bcaststr, NULL);
+    virCommandAddArgList(cmd, "dev", ifname, NULL);
+
+    if (virCommandRun(cmd, NULL) < 0)
+        goto cleanup;
+
+    ret = 0;
+cleanup:
+    VIR_FREE(addrstr);
+    VIR_FREE(bcaststr);
+    virCommandFree(cmd);
+    return ret;
+}
+
+/**
+ * virNetDevClearIPv4Address:
+ * @ifname: the interface name
+ * @addr: the IP address (IPv4 or IPv6)
+ * @prefix: number of 1 bits in the netmask
+ *
+ * Delete an IP address from an interface.
+ *
+ * Returns 0 in case of success or -1 in case of error.
+ */
+
+int virNetDevClearIPv4Address(const char *ifname,
+                              virSocketAddr *addr,
+                              unsigned int prefix)
+{
+    virCommandPtr cmd = NULL;
+    char *addrstr;
+    int ret = -1;
+
+    if (!(addrstr = virSocketFormatAddr(addr)))
+        goto cleanup;
+    cmd = virCommandNew(IP_PATH);
+    virCommandAddArgList(cmd, "addr", "del", NULL);
+    virCommandAddArgFormat(cmd, "%s/%u", addrstr, prefix);
+    virCommandAddArgList(cmd, "dev", ifname, NULL);
+
+    if (virCommandRun(cmd, NULL) < 0)
+        goto cleanup;
+
+    ret = 0;
+cleanup:
+    VIR_FREE(addrstr);
+    virCommandFree(cmd);
+    return ret;
+}
diff --git a/src/util/virnetdev.h b/src/util/virnetdev.h
new file mode 100644
index 0000000..cae98b7
--- /dev/null
+++ b/src/util/virnetdev.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2007-2011 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ * Authors:
+ *     Mark McLoughlin <markmc at redhat.com>
+ *     Daniel P. Berrange <berrange at redhat.com>
+ */
+
+#ifndef __VIR_NETDEV_H__
+# define __VIR_NETDEV_H__
+
+# include "network.h"
+
+int virNetDevExists(const char *brname)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
+
+int virNetDevSetOnline(const char *ifname,
+                       bool online)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
+int virNetDevIsOnline(const char *ifname,
+                      bool *online)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
+
+int virNetDevSetIPv4Addres(const char *ifname,
+                           virSocketAddr *addr,
+                           unsigned int prefix)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
+int virNetDevClearIPv4Address(const char *ifname,
+                              virSocketAddr *addr,
+                              unsigned int prefix)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
+
+
+int virNetDevSetMAC(const char *ifname,
+                    const unsigned char *macaddr)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
+int virNetDevGetMAC(const char *ifname,
+                    unsigned char *macaddr)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
+int virNetDevSetMTU(const char *ifname,
+                    int mtu)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
+int virNetDevSetMTUFromDevice(const char *ifname,
+                              const char *otherifname)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
+int virNetDevGetMTU(const char *ifname)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
+
+#endif /* __VIR_NETDEV_H__ */
diff --git a/src/util/virnetdevbridge.c b/src/util/virnetdevbridge.c
new file mode 100644
index 0000000..701d9ff
--- /dev/null
+++ b/src/util/virnetdevbridge.c
@@ -0,0 +1,527 @@
+/*
+ * Copyright (C) 2007-2011 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ * Authors:
+ *     Mark McLoughlin <markmc at redhat.com>
+ *     Daniel P. Berrange <berrange at redhat.com>
+ */
+
+#include <config.h>
+
+#include "virnetdevbridge.h"
+#include "virterror_internal.h"
+#include "util.h"
+#include "virfile.h"
+#include "memory.h"
+#include "intprops.h"
+
+#include <sys/ioctl.h>
+#ifdef HAVE_NET_IF_H
+# include <net/if.h>
+#endif
+#ifdef __linux__
+# include <linux/sockios.h>
+# include <linux/param.h>     /* HZ                 */
+# include <linux/if_bridge.h> /* SYSFS_BRIDGE_ATTR  */
+
+# define JIFFIES_TO_MS(j) (((j)*1000)/HZ)
+# define MS_TO_JIFFIES(ms) (((ms)*HZ)/1000)
+#endif
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+
+#ifdef HAVE_NET_IF_H
+static int virNetDevSetupControlFull(const char *ifname,
+                                     struct ifreq *ifr,
+                                     int domain,
+                                     int type)
+{
+    int fd;
+
+    if (ifname && ifr) {
+        memset(ifr, 0, sizeof(*ifr));
+
+        if (virStrcpyStatic(ifr->ifr_name, ifname) == NULL) {
+            virReportSystemError(ERANGE,
+                                 _("Network interface name '%s' is too long"),
+                                 ifname);
+            return -1;
+        }
+    }
+
+    if ((fd = socket(domain, type, 0)) < 0) {
+        virReportSystemError(errno, "%s",
+                             _("Cannot open network interface control socket"));
+        return -1;
+    }
+
+    if (virSetInherit(fd, false) < 0) {
+        virReportSystemError(errno, "%s",
+                             _("Cannot set close-on-exec flag for socket"));
+        VIR_FORCE_CLOSE(fd);
+        return -1;
+    }
+
+    return fd;
+}
+
+
+static int virNetDevSetupControl(const char *ifname,
+                                 struct ifreq *ifr)
+{
+    return virNetDevSetupControlFull(ifname, ifr, AF_PACKET, SOCK_DGRAM);
+}
+#endif
+
+#ifdef __linux__
+# define SYSFS_NET_DIR "/sys/class/net"
+/*
+ * Bridge parameters can be set via sysfs on newish kernels,
+ * or by  ioctl on older kernels. Perhaps we could just use
+ * ioctl for every kernel, but its not clear what the long
+ * term lifespan of the ioctl interface is...
+ */
+static int virNetDevBridgeSet(const char *brname,
+                              const char *paramname,  /* sysfs param name */
+                              unsigned long value,    /* new value */
+                              int fd,                 /* control socket */
+                              struct ifreq *ifr)      /* pre-filled bridge name */
+{
+    char *path = NULL;
+    int ret = -1;
+
+    if (virAsprintf(&path, "%s/%s/bridge/%s", SYSFS_NET_DIR, brname, paramname) < 0) {
+        virReportOOMError();
+        return -1;
+    }
+
+    if (virFileExists(path)) {
+        char valuestr[INT_BUFSIZE_BOUND(value)];
+        snprintf(valuestr, sizeof(valuestr), "%lu", value);
+        if (virFileWriteStr(path, valuestr, 0) < 0) {
+            virReportSystemError(errno,
+                                 _("Unable to set bridge %s %s"), brname, paramname);
+            goto cleanup;
+        }
+    } else {
+        unsigned long paramid;
+        if (STREQ(paramname, "stp_state")) {
+            paramid = BRCTL_SET_BRIDGE_STP_STATE;
+        } else if (STREQ(paramname, "forward_delay")) {
+            paramid = BRCTL_SET_BRIDGE_FORWARD_DELAY;
+        } else {
+            virReportSystemError(EINVAL,
+                                 _("Unable to set bridge %s %s"), brname, paramname);
+            goto cleanup;
+        }
+        unsigned long args[] = { paramid, value, 0, 0 };
+        ifr->ifr_data = (char*)&args;
+        if (ioctl(fd, SIOCDEVPRIVATE, ifr) < 0) {
+            virReportSystemError(errno,
+                                 _("Unable to set bridge %s %s"), brname, paramname);
+            goto cleanup;
+        }
+    }
+
+    ret = 0;
+cleanup:
+    VIR_FREE(path);
+    return ret;
+}
+
+
+static int virNetDevBridgeGet(const char *brname,
+                              const char *paramname,  /* sysfs param name */
+                              unsigned long *value,   /* current value */
+                              int fd,                 /* control socket */
+                              struct ifreq *ifr)      /* pre-filled bridge name */
+{
+    char *path = NULL;
+    int ret = -1;
+
+    if (virAsprintf(&path, "%s/%s/bridge/%s", SYSFS_NET_DIR, brname, paramname) < 0) {
+        virReportOOMError();
+        return -1;
+    }
+
+    if (virFileExists(path)) {
+        char *valuestr;
+        if (virFileReadAll(path, INT_BUFSIZE_BOUND(unsigned long), &valuestr) < 0)
+            goto cleanup;
+
+        if (virStrToLong_ul(valuestr, NULL, 10, value) < 0) {
+            virReportSystemError(EINVAL,
+                                 _("Unable to get bridge %s %s"), brname, paramname);
+        }
+    } else {
+        struct __bridge_info info;
+        unsigned long args[] = { BRCTL_GET_BRIDGE_INFO, (unsigned long)&info, 0, 0 };
+        ifr->ifr_data = (char*)&args;
+        if (ioctl(fd, SIOCDEVPRIVATE, ifr) < 0) {
+            virReportSystemError(errno,
+                                 _("Unable to get bridge %s %s"), brname, paramname);
+            goto cleanup;
+        }
+
+        if (STREQ(paramname, "stp_state")) {
+            *value = info.stp_enabled;
+        } else if (STREQ(paramname, "forward_delay")) {
+            *value = info.forward_delay;
+        } else {
+            virReportSystemError(EINVAL,
+                                 _("Unable to get bridge %s %s"), brname, paramname);
+            goto cleanup;
+        }
+    }
+
+    ret = 0;
+cleanup:
+    VIR_FREE(path);
+    return ret;
+}
+#endif /* __linux__ */
+
+
+/**
+ * virNetDevBridgeCreate:
+ * @brname: the bridge name
+ *
+ * This function register a new bridge
+ *
+ * Returns 0 in case of success or -1 on failure
+ */
+#ifdef SIOCBRADDBR
+int virNetDevBridgeCreate(const char *brname)
+{
+    int fd = -1;
+    int ret = -1;
+
+    if ((fd = virNetDevSetupControl(NULL, NULL)) < 0)
+        return -1;
+
+    if (ioctl(fd, SIOCBRADDBR, brname) < 0) {
+        virReportSystemError(errno,
+                             _("Unable to create bridge %s"), brname);
+        goto cleanup;
+    }
+
+    ret = 0;
+
+cleanup:
+    VIR_FORCE_CLOSE(fd);
+    return ret;
+}
+#else
+int virNetDevBridgeCreate(const char *brname)
+{
+    virReportSystemError(ENOSYS,
+                         _("Unable to create bridge %s"), brname);
+    return -1;
+}
+#endif
+
+/**
+ * virNetDevBridgeDelete:
+ * @brname: the bridge name
+ *
+ * Remove a bridge from the layer.
+ *
+ * Returns 0 in case of success or an errno code in case of failure.
+ */
+#ifdef SIOCBRDELBR
+int virNetDevBridgeDelete(const char *brname)
+{
+    int fd = -1;
+    int ret = -1;
+
+    if ((fd = virNetDevSetupControl(NULL, NULL)) < 0)
+        return -1;
+
+    if (ioctl(fd, SIOCBRDELBR, brname) < 0) {
+        virReportSystemError(errno,
+                             _("Unable to delete bridge %s"), brname);
+        goto cleanup;
+    }
+
+    ret = 0;
+
+cleanup:
+    VIR_FORCE_CLOSE(fd);
+    return ret;
+}
+#else
+int virNetDevBridgeDelete(const char *brname ATTRIBUTE_UNUSED)
+{
+    virReportSystemError(errno,
+                         _("Unable to delete bridge %s"), brname);
+    return EINVAL;
+}
+#endif
+
+/**
+ * virNetDevBridgeAddPort:
+ * @brname: the bridge name
+ * @ifname: the network interface name
+ *
+ * Adds an interface to a bridge
+ *
+ * Returns 0 in case of success or an errno code in case of failure.
+ */
+#ifdef SIOCBRADDIF
+int virNetDevBridgeAddPort(const char *brname,
+                           const char *ifname)
+{
+    int fd = -1;
+    int ret = -1;
+    struct ifreq ifr;
+
+    if ((fd = virNetDevSetupControl(brname, &ifr)) < 0)
+        return -1;
+
+    if (!(ifr.ifr_ifindex = if_nametoindex(ifname))) {
+        virReportSystemError(errno,
+                             _("Unable to get interface index for %s"), ifname);
+        goto cleanup;
+    }
+
+    if (ioctl(fd, SIOCBRADDIF, &ifr) < 0) {
+        virReportSystemError(errno,
+                             _("Unable to add bridge %s port %s"), brname, ifname);
+        goto cleanup;
+    }
+
+    ret = 0;
+cleanup:
+    VIR_FORCE_CLOSE(fd);
+    return ret;
+}
+#else
+int virNetDevBridgeAddPort(const char *brname,
+                           const char *ifname)
+{
+    virReportSystemError(ENOSYS,
+                         _("Unable to add bridge %s port %s"), brname, ifname);
+    return -1;
+}
+#endif
+
+/**
+ * virNetDevBridgeRemovePort:
+ * @brname: the bridge name
+ * @ifname: the network interface name
+ *
+ * Removes an interface from a bridge
+ *
+ * Returns 0 in case of success or an errno code in case of failure.
+ */
+#ifdef SIOCBRDELIF
+int virNetDevBridgeRemovePort(const char *brname,
+                              const char *ifname)
+{
+    int fd = -1;
+    int ret = -1;
+    struct ifreq ifr;
+
+    if ((fd = virNetDevSetupControl(brname, &ifr)) < 0)
+        return -1;
+
+    if (!(ifr.ifr_ifindex = if_nametoindex(ifname))) {
+        virReportSystemError(errno,
+                             _("Unable to get interface index for %s"), ifname);
+
+        goto cleanup;
+    }
+
+    if (ioctl(fd, SIOCBRDELIF, &ifr) < 0) {
+        virReportSystemError(errno,
+                             _("Unable to remove bridge %s port %s"), brname, ifname);
+        goto cleanup;
+    }
+
+    ret = 0;
+cleanup:
+    VIR_FORCE_CLOSE(fd);
+    return ret;
+}
+#else
+int virNetDevBridgeRemovePort(const char *brname,
+                              const char *ifname)
+{
+    virReportSystemError(errno,
+                         _("Unable to remove bridge %s port %s"), brname, ifname);
+    return -1;
+}
+#endif
+
+
+#ifdef __linux__
+/**
+ * virNetDevBridgeSetSTPDelay:
+ * @brname: the bridge name
+ * @delay: delay in seconds
+ *
+ * Set the bridge forward delay
+ *
+ * Returns 0 in case of success or -1 on failure
+ */
+
+int virNetDevBridgeSetSTPDelay(const char *brname,
+                               int delay)
+{
+    int fd = -1;
+    int ret = -1;
+    struct ifreq ifr;
+
+    if ((fd = virNetDevSetupControl(brname, &ifr)) < 0)
+        goto cleanup;
+
+    ret = virNetDevBridgeSet(brname, "stp_state", MS_TO_JIFFIES(delay),
+                             fd, &ifr);
+
+cleanup:
+    VIR_FORCE_CLOSE(fd);
+    return ret;
+}
+
+
+/**
+ * virNetDevBridgeGetSTPDelay:
+ * @brname: the bridge device name
+ * @delayms: the forward delay in milliseconds
+ *
+ * Retrives the forward delay for the bridge device @brname
+ * storing it in @delayms. The forward delay is only meaningful
+ * if STP is enabled
+ *
+ * Returns 0 on success, -1 on error+
+ */
+int virNetDevBridgeGetSTPDelay(const char *brname,
+                               int *delayms)
+{
+    int fd = -1;
+    int ret = -1;
+    struct ifreq ifr;
+    unsigned long i;
+
+    if ((fd = virNetDevSetupControl(brname, &ifr)) < 0)
+        goto cleanup;
+
+    ret = virNetDevBridgeGet(brname, "stp_state", &i,
+                             fd, &ifr);
+    *delayms = JIFFIES_TO_MS(i);
+
+cleanup:
+    VIR_FORCE_CLOSE(fd);
+    return ret;
+}
+
+
+/**
+ * virNetDevBridgeSetSTP:
+ * @brname: the bridge name
+ * @enable: 1 to enable, 0 to disable
+ *
+ * Control whether the bridge participates in the spanning tree protocol,
+ * in general don't disable it without good reasons.
+ *
+ * Returns 0 in case of success or -1 on failure
+ */
+int virNetDevBridgeSetSTP(const char *brname,
+                          bool enable)
+{
+    int fd = -1;
+    int ret = -1;
+    struct ifreq ifr;
+
+    if ((fd = virNetDevSetupControl(brname, &ifr)) < 0)
+        goto cleanup;
+
+    ret = virNetDevBridgeSet(brname, "stp_state", enable ? 1 : 0,
+                             fd, &ifr);
+
+cleanup:
+    VIR_FORCE_CLOSE(fd);
+    return ret;
+}
+
+
+/**
+ * virNetDevBridgeGetSTP:
+ * @brname: the bridge device name
+ * @enabled: returns the STP state
+ *
+ * Determine the state of the spanning tree protocol on
+ * the device @brname, returning the state in @enabled
+ *
+ * Returns 0 on success, -1 on error
+ */
+int virNetDevBridgeGetSTP(const char *brname,
+                          bool *enabled)
+{
+    int fd = -1;
+    int ret = -1;
+    struct ifreq ifr;
+    unsigned long i;
+
+    if ((fd = virNetDevSetupControl(brname, &ifr)) < 0)
+        goto cleanup;
+
+    ret = virNetDevBridgeGet(brname, "stp_state", &i,
+                             fd, &ifr);
+    *enabled = i ? true : false;
+
+cleanup:
+    VIR_FORCE_CLOSE(fd);
+    return ret;
+}
+#else /* !__linux__ */
+int virNetDevBridgeSetSTPDelay(const char *brname,
+                               int delay ATTRIBUTE_UNUSED)
+{
+    virReportSystemError(ENOSYS,
+                         _("Unable to set STP delay on %s on this platform"),
+                         brname);
+    return -1;
+}
+int virNetDevBridgeGetSTPDelay(const char *brname,
+                               int *delay ATTRIBUTE_UNUSED)
+{
+    virReportSystemError(ENOSYS,
+                         _("Unable to get STP delay on %s on this platform"),
+                         brname);
+    return -1;
+}
+
+int virNetDevBridgeSetSTP(const char *brname,
+                          bool enable ATTRIBUTE_UNUSED)
+
+{
+    virReportSystemError(ENOSYS,
+                         _("Unable to set STP on %s on this platform"),
+                         brname);
+    return -1;
+}
+int virNetDevBridgeGetSTP(const char *brname,
+                          bool *enable ATTRIBUTE_UNUSED)
+{
+    virReportSystemError(ENOSYS,
+                         _("Unable to get STP on %s on this platform"),
+                         brname);
+    return -1;
+}
+#endif /* __linux__ */
diff --git a/src/util/virnetdevbridge.h b/src/util/virnetdevbridge.h
new file mode 100644
index 0000000..98fc1d2
--- /dev/null
+++ b/src/util/virnetdevbridge.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2007-2011 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ * Authors:
+ *     Mark McLoughlin <markmc at redhat.com>
+ *     Daniel P. Berrange <berrange at redhat.com>
+ */
+
+#ifndef __VIR_NETDEV_BRIDGE_H__
+# define __VIR_NETDEV_BRIDGE_H__
+
+# include "internal.h"
+
+int virNetDevBridgeCreate(const char *brname)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
+int virNetDevBridgeDelete(const char *brname)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
+
+int virNetDevBridgeAddPort(const char *brname,
+                           const char *ifname)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
+
+int virNetDevBridgeRemovePort(const char *brname,
+                              const char *ifname)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
+
+int virNetDevBridgeSetSTPDelay(const char *brname,
+                               int delay)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
+int virNetDevBridgeGetSTPDelay(const char *brname,
+                               int *delay)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
+int virNetDevBridgeSetSTP(const char *brname,
+                          bool enable)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
+int virNetDevBridgeGetSTP(const char *brname,
+                          bool *enable)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
+
+#endif /* __VIR_NETDEV_BRIDGE_H__ */
diff --git a/src/util/virnetdevtap.c b/src/util/virnetdevtap.c
new file mode 100644
index 0000000..5c60925
--- /dev/null
+++ b/src/util/virnetdevtap.c
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 2007-2011 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ * Authors:
+ *     Mark McLoughlin <markmc at redhat.com>
+ *     Daniel P. Berrange <berrange at redhat.com>
+ */
+
+#include <config.h>
+
+#include "virnetdevtap.h"
+#include "virnetdev.h"
+#include "virnetdevbridge.h"
+#include "virterror_internal.h"
+#include "virfile.h"
+#include "virterror_internal.h"
+#include "memory.h"
+#include "logging.h"
+
+#include <sys/ioctl.h>
+#ifdef HAVE_NET_IF_H
+# include <net/if.h>
+#endif
+#include <fcntl.h>
+#ifdef __linux__
+# include <linux/if_tun.h>    /* IFF_TUN, IFF_NO_PI */
+#endif
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+/**
+ * virNetDevProbeVnetHdr:
+ * @tapfd: a tun/tap file descriptor
+ *
+ * Check whether it is safe to enable the IFF_VNET_HDR flag on the
+ * tap interface.
+ *
+ * Setting IFF_VNET_HDR enables QEMU's virtio_net driver to allow
+ * guests to pass larger (GSO) packets, with partial checksums, to
+ * the host. This greatly increases the achievable throughput.
+ *
+ * It is only useful to enable this when we're setting up a virtio
+ * interface. And it is only *safe* to enable it when we know for
+ * sure that a) qemu has support for IFF_VNET_HDR and b) the running
+ * kernel implements the TUNGETIFF ioctl(), which qemu needs to query
+ * the supplied tapfd.
+ *
+ * Returns 1 if VnetHdr is supported, 0 if not supported
+ */
+#ifdef IFF_VNET_HDR
+static int
+virNetDevProbeVnetHdr(int tapfd)
+{
+# if defined(IFF_VNET_HDR) && defined(TUNGETFEATURES) && defined(TUNGETIFF)
+    unsigned int features;
+    struct ifreq dummy;
+
+    if (ioctl(tapfd, TUNGETFEATURES, &features) != 0) {
+        VIR_INFO("Not enabling IFF_VNET_HDR; "
+                 "TUNGETFEATURES ioctl() not implemented");
+        return 0;
+    }
+
+    if (!(features & IFF_VNET_HDR)) {
+        VIR_INFO("Not enabling IFF_VNET_HDR; "
+                 "TUNGETFEATURES ioctl() reports no IFF_VNET_HDR");
+        return 0;
+    }
+
+    /* The kernel will always return -1 at this point.
+     * If TUNGETIFF is not implemented then errno == EBADFD.
+     */
+    if (ioctl(tapfd, TUNGETIFF, &dummy) != -1 || errno != EBADFD) {
+        VIR_INFO("Not enabling IFF_VNET_HDR; "
+                 "TUNGETIFF ioctl() not implemented");
+        return 0;
+    }
+
+    VIR_INFO("Enabling IFF_VNET_HDR");
+
+    return 1;
+# else
+    (void) tapfd;
+    VIR_INFO("Not enabling IFF_VNET_HDR; disabled at build time");
+    return 0;
+# endif
+}
+#endif
+
+
+#ifdef TUNSETIFF
+/**
+ * brCreateTap:
+ * @ifname: the interface name
+ * @vnet_hr: whether to try enabling IFF_VNET_HDR
+ * @tapfd: file descriptor return value for the new tap device
+ *
+ * Creates a tap interface.
+ * If the @tapfd parameter is supplied, the open tap device file
+ * descriptor will be returned, otherwise the TAP device will be made
+ * persistent and closed. The caller must use brDeleteTap to remove
+ * a persistent TAP devices when it is no longer needed.
+ *
+ * Returns 0 in case of success or an errno code in case of failure.
+ */
+int virNetDevTapCreate(char **ifname,
+                       int vnet_hdr ATTRIBUTE_UNUSED,
+                       int *tapfd)
+{
+    int fd;
+    struct ifreq ifr;
+    int ret = -1;
+
+    if ((fd = open("/dev/net/tun", O_RDWR)) < 0) {
+        virReportSystemError(errno, "%s",
+                             _("Unable to open /dev/net/tun, is tun module loaded?"));
+        return -1;
+    }
+
+    memset(&ifr, 0, sizeof(ifr));
+
+    ifr.ifr_flags = IFF_TAP|IFF_NO_PI;
+
+# ifdef IFF_VNET_HDR
+    if (vnet_hdr && virNetDevProbeVnetHdr(fd))
+        ifr.ifr_flags |= IFF_VNET_HDR;
+# endif
+
+    if (virStrcpyStatic(ifr.ifr_name, *ifname) == NULL) {
+        virReportSystemError(ERANGE,
+                             _("Network interface name '%s' is too long"),
+                             *ifname);
+        goto cleanup;
+
+    }
+
+    if (ioctl(fd, TUNSETIFF, &ifr) < 0) {
+        virReportSystemError(errno,
+                             _("Unable to create tap device %s"),
+                             NULLSTR(*ifname));
+        goto cleanup;
+    }
+
+    if (!tapfd &&
+        (errno = ioctl(fd, TUNSETPERSIST, 1))) {
+        virReportSystemError(errno,
+                             _("Unable to set tap device %s to persistent"),
+                             NULLSTR(*ifname));
+        goto cleanup;
+    }
+
+    VIR_FREE(*ifname);
+    if (!(*ifname = strdup(ifr.ifr_name))) {
+        virReportOOMError();
+        goto cleanup;
+    }
+    if (tapfd)
+        *tapfd = fd;
+    else
+        VIR_FORCE_CLOSE(fd);
+
+    ret = 0;
+
+cleanup:
+    if (ret < 0)
+        VIR_FORCE_CLOSE(fd);
+
+    return ret;
+}
+
+
+int virNetDevTapDelete(const char *ifname)
+{
+    struct ifreq try;
+    int fd;
+    int ret = -1;
+
+    if ((fd = open("/dev/net/tun", O_RDWR)) < 0) {
+        virReportSystemError(errno, "%s",
+                             _("Unable to open /dev/net/tun, is tun module loaded?"));
+        return -1;
+    }
+
+    memset(&try, 0, sizeof(struct ifreq));
+    try.ifr_flags = IFF_TAP|IFF_NO_PI;
+
+    if (virStrcpyStatic(try.ifr_name, ifname) == NULL) {
+        virReportSystemError(ERANGE,
+                             _("Network interface name '%s' is too long"),
+                             ifname);
+        goto cleanup;
+    }
+
+    if (ioctl(fd, TUNSETIFF, &try) < 0) {
+        virReportSystemError(errno, "%s",
+                             _("Unable to associate TAP device"));
+        goto cleanup;
+    }
+
+    if (ioctl(fd, TUNSETPERSIST, 0) < 0) {
+        virReportSystemError(errno, "%s",
+                             _("Unable to make TAP device non-persistent"));
+        goto cleanup;
+    }
+
+    ret = 0;
+
+cleanup:
+    VIR_FORCE_CLOSE(fd);
+    return ret;
+}
+#else /* ! TUNSETIFF */
+int virNetDevTapCreate(char **ifname ATTRIBUTE_UNUSED,
+                       int vnet_hdr ATTRIBUTE_UNUSED,
+                       int *tapfd ATTRIBUTE_UNUSED)
+{
+    virReportSystemError(ENOSYS, "%s",
+                         _("Unable to create TAP devices on this platform"));
+    return -1;
+}
+int virNetDevTapDelete(const char *ifname ATTRIBUTE_UNUSED)
+{
+    virReportSystemError(ENOSYS, "%s",
+                         _("Unable to delete TAP devices on this platform"));
+    return -1;
+}
+#endif /* ! TUNSETIFF */
+
+
+/**
+ * virNetDevTapCreateInBridgePort:
+ * @brname: the bridge name
+ * @ifname: the interface name (or name template)
+ * @macaddr: desired MAC address (VIR_MAC_BUFLEN long)
+ * @vnet_hdr: whether to try enabling IFF_VNET_HDR
+ * @tapfd: file descriptor return value for the new tap device
+ *
+ * This function creates a new tap device on a bridge. @ifname can be either
+ * a fixed name or a name template with '%d' for dynamic name allocation.
+ * in either case the final name for the bridge will be stored in @ifname.
+ * If the @tapfd parameter is supplied, the open tap device file
+ * descriptor will be returned, otherwise the TAP device will be made
+ * persistent and closed. The caller must use brDeleteTap to remove
+ * a persistent TAP devices when it is no longer needed.
+ *
+ * Returns 0 in case of success or -1 on failure
+ */
+int virNetDevTapCreateInBridgePort(const char *brname,
+                                   char **ifname,
+                                   const unsigned char *macaddr,
+                                   int vnet_hdr,
+                                   bool up,
+                                   int *tapfd)
+{
+    if (virNetDevTapCreate(ifname, vnet_hdr, tapfd) < 0)
+        return -1;
+
+    /* We need to set the interface MAC before adding it
+     * to the bridge, because the bridge assumes the lowest
+     * MAC of all enslaved interfaces & we don't want it
+     * seeing the kernel allocate random MAC for the TAP
+     * device before we set our static MAC.
+     */
+    if (virNetDevSetMAC(*ifname, macaddr) < 0)
+        goto error;
+
+    /* We need to set the interface MTU before adding it
+     * to the bridge, because the bridge will have its
+     * MTU adjusted automatically when we add the new interface.
+     */
+    if (virNetDevSetMTUFromDevice(*ifname, brname) < 0)
+        goto error;
+
+    if (virNetDevBridgeAddPort(brname, *ifname) < 0)
+        goto error;
+
+    if (virNetDevSetOnline(*ifname, up) < 0)
+        goto error;
+
+    return 0;
+
+ error:
+    VIR_FORCE_CLOSE(*tapfd);
+
+    return errno;
+}
diff --git a/src/util/virnetdevtap.h b/src/util/virnetdevtap.h
new file mode 100644
index 0000000..fb35ac5
--- /dev/null
+++ b/src/util/virnetdevtap.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2007-2011 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ * Authors:
+ *     Mark McLoughlin <markmc at redhat.com>
+ *     Daniel P. Berrange <berrange at redhat.com>
+ */
+
+#ifndef __VIR_NETDEV_TAP_H__
+# define __VIR_NETDEV_TAP_H__
+
+# include "internal.h"
+
+int virNetDevTapCreate(char **ifname,
+                       int vnet_hdr,
+                       int *tapfd)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
+
+int virNetDevTapDelete(const char *ifname)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
+
+int virNetDevTapCreateInBridgePort(const char *brname,
+                                   char **ifname,
+                                   const unsigned char *macaddr,
+                                   int vnet_hdr,
+                                   bool up,
+                                   int *tapfd)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
+    ATTRIBUTE_RETURN_CHECK;
+
+#endif /* __VIR_NETDEV_TAP_H__ */
-- 
1.7.6.4




More information about the libvir-list mailing list