[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