On 11/03/2011 01:30 PM, Daniel P. Berrange wrote:
From: "Daniel P. Berrange"<berrange(a)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(a)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(a)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(a)redhat.com>
+ * Daniel P. Berrange<berrange(a)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(a)redhat.com>
+ * Daniel P. Berrange<berrange(a)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(a)redhat.com>
+ * Daniel P. Berrange<berrange(a)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(a)redhat.com>
+ * Daniel P. Berrange<berrange(a)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(a)redhat.com>
+ * Daniel P. Berrange<berrange(a)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(a)redhat.com>
+ * Daniel P. Berrange<berrange(a)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