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

Stefan Berger stefanb at linux.vnet.ibm.com
Tue Nov 8 16:09:49 UTC 2011


On 11/03/2011 01:30 PM, Daniel P. Berrange wrote:
> 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,
ENOSYS
> +                         _("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)
> +

I guess other network devices than taps can also use this function, so 
it doesn't need Tap in the name of the function. Maybe move it into the 
virnetdev.c file ?
> {
> +# 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__ */
ACK with nits addressed...

    Stefan




More information about the libvir-list mailing list