Split bridge.h into three separate files
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
2011-11-02 13:41:58 +00:00
|
|
|
/*
|
2012-03-05 00:21:16 +00:00
|
|
|
* Copyright (C) 2007-2012 Red Hat, Inc.
|
Split bridge.h into three separate files
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
2011-11-02 13:41:58 +00:00
|
|
|
*
|
|
|
|
* 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@redhat.com>
|
|
|
|
* Daniel P. Berrange <berrange@redhat.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
util: centralize tap device MAC address 1st byte "0xFE" modification
When a tap device for a domain is created and attached to a bridge,
the first byte of the tap device MAC address is set to 0xFE, while the
rest is set to match the MAC address that will be presented to the
guest as its network device MAC address. Setting this high value in
the tap's MAC address discourages the bridge from using the tap
device's MAC address as the bridge's own MAC address (Linux bridges
always take on the lowest numbered MAC address of all attached devices
as their own).
In one case within libvirt, a tap device is created and attached to
the bridge with the intent that its MAC address be taken on by the
bridge as its own (this is used to assure that the bridge has a fixed
MAC address to prevent network outages created by the bridge MAC
address "flapping" as guests are started and stopped). In this case,
the first byte of the mac address is *not* altered to 0xFE.
In the current code, callers to virNetDevTapCreateInBridgePort each
make the MAC address modification themselves before calling, which
leads to code duplication, and also prevents lower level functions
from knowing the real MAC address being used by the guest. The problem
here is that openvswitch bridges must be informed about this MAC
address, or they will be unable to pass traffic to/from the guest.
This patch centralizes the location of the MAC address "0xFE fixup"
into virNetDevTapCreateInBridgePort(), meaning 1) callers of this
function no longer need the extra strange bit of code, and 2)
bitNetDevTapCreateBridgeInPort itself now is called with the guest's
unaltered MAC address, and can pass it on, unmodified, to
virNetDevOpenvswitchAddPort.
There is no other behavioral change created by this patch.
2012-02-16 23:49:57 +00:00
|
|
|
#include "virmacaddr.h"
|
Split bridge.h into three separate files
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
2011-11-02 13:41:58 +00:00
|
|
|
#include "virnetdevtap.h"
|
|
|
|
#include "virnetdev.h"
|
|
|
|
#include "virnetdevbridge.h"
|
2012-02-10 21:09:00 +00:00
|
|
|
#include "virnetdevopenvswitch.h"
|
Split bridge.h into three separate files
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
2011-11-02 13:41:58 +00:00
|
|
|
#include "virterror_internal.h"
|
|
|
|
#include "virfile.h"
|
|
|
|
#include "virterror_internal.h"
|
|
|
|
#include "memory.h"
|
|
|
|
#include "logging.h"
|
Split src/util/network.{c,h} into 5 pieces
The src/util/network.c file is a dumping ground for many different
APIs. Split it up into 5 pieces, along functional lines
- src/util/virnetdevbandwidth.c: virNetDevBandwidth type & helper APIs
- src/util/virnetdevvportprofile.c: virNetDevVPortProfile type & helper APIs
- src/util/virsocketaddr.c: virSocketAddr and APIs
- src/conf/netdev_bandwidth_conf.c: XML parsing / formatting
for virNetDevBandwidth
- src/conf/netdev_vport_profile_conf.c: XML parsing / formatting
for virNetDevVPortProfile
* src/util/network.c, src/util/network.h: Split into 5 pieces
* src/conf/netdev_bandwidth_conf.c, src/conf/netdev_bandwidth_conf.h,
src/conf/netdev_vport_profile_conf.c, src/conf/netdev_vport_profile_conf.h,
src/util/virnetdevbandwidth.c, src/util/virnetdevbandwidth.h,
src/util/virnetdevvportprofile.c, src/util/virnetdevvportprofile.h,
src/util/virsocketaddr.c, src/util/virsocketaddr.h: New pieces
* daemon/libvirtd.h, daemon/remote.c, src/conf/domain_conf.c,
src/conf/domain_conf.h, src/conf/network_conf.c,
src/conf/network_conf.h, src/conf/nwfilter_conf.h,
src/esx/esx_util.h, src/network/bridge_driver.c,
src/qemu/qemu_conf.c, src/rpc/virnetsocket.c,
src/rpc/virnetsocket.h, src/util/dnsmasq.h, src/util/interface.h,
src/util/iptables.h, src/util/macvtap.c, src/util/macvtap.h,
src/util/virnetdev.h, src/util/virnetdevtap.c,
tools/virsh.c: Update include files
2011-11-02 15:40:08 +00:00
|
|
|
#include "util.h"
|
Split bridge.h into three separate files
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
2011-11-02 13:41:58 +00:00
|
|
|
|
|
|
|
#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
|
|
|
|
|
2012-03-05 00:21:16 +00:00
|
|
|
#define virNetDevTapError(code, ...) \
|
|
|
|
virReportErrorHelper(VIR_FROM_NONE, code, __FILE__, \
|
|
|
|
__FUNCTION__, __LINE__, __VA_ARGS__)
|
|
|
|
|
Split bridge.h into three separate files
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
2011-11-02 13:41:58 +00:00
|
|
|
/**
|
|
|
|
* virNetDevProbeVnetHdr:
|
|
|
|
* @tapfd: a tun/tap file descriptor
|
|
|
|
*
|
|
|
|
* Check whether it is safe to enable the IFF_VNET_HDR flag on the
|
|
|
|
* tap interface.
|
|
|
|
*
|
|
|
|
* Setting IFF_VNET_HDR enables QEMU's virtio_net driver to allow
|
|
|
|
* guests to pass larger (GSO) packets, with partial checksums, to
|
|
|
|
* the host. This greatly increases the achievable throughput.
|
|
|
|
*
|
|
|
|
* It is only useful to enable this when we're setting up a virtio
|
|
|
|
* interface. And it is only *safe* to enable it when we know for
|
|
|
|
* sure that a) qemu has support for IFF_VNET_HDR and b) the running
|
|
|
|
* kernel implements the TUNGETIFF ioctl(), which qemu needs to query
|
|
|
|
* the supplied tapfd.
|
|
|
|
*
|
|
|
|
* Returns 1 if VnetHdr is supported, 0 if not supported
|
|
|
|
*/
|
|
|
|
#ifdef IFF_VNET_HDR
|
|
|
|
static int
|
|
|
|
virNetDevProbeVnetHdr(int tapfd)
|
|
|
|
{
|
|
|
|
# if defined(IFF_VNET_HDR) && defined(TUNGETFEATURES) && defined(TUNGETIFF)
|
|
|
|
unsigned int features;
|
|
|
|
struct ifreq dummy;
|
|
|
|
|
|
|
|
if (ioctl(tapfd, TUNGETFEATURES, &features) != 0) {
|
|
|
|
VIR_INFO("Not enabling IFF_VNET_HDR; "
|
|
|
|
"TUNGETFEATURES ioctl() not implemented");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(features & IFF_VNET_HDR)) {
|
|
|
|
VIR_INFO("Not enabling IFF_VNET_HDR; "
|
|
|
|
"TUNGETFEATURES ioctl() reports no IFF_VNET_HDR");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The kernel will always return -1 at this point.
|
|
|
|
* If TUNGETIFF is not implemented then errno == EBADFD.
|
|
|
|
*/
|
|
|
|
if (ioctl(tapfd, TUNGETIFF, &dummy) != -1 || errno != EBADFD) {
|
|
|
|
VIR_INFO("Not enabling IFF_VNET_HDR; "
|
|
|
|
"TUNGETIFF ioctl() not implemented");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_INFO("Enabling IFF_VNET_HDR");
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
# else
|
|
|
|
(void) tapfd;
|
|
|
|
VIR_INFO("Not enabling IFF_VNET_HDR; disabled at build time");
|
|
|
|
return 0;
|
|
|
|
# endif
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef TUNSETIFF
|
|
|
|
/**
|
2012-03-01 20:35:30 +00:00
|
|
|
* virNetDevTapCreate:
|
Split bridge.h into three separate files
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
2011-11-02 13:41:58 +00:00
|
|
|
* @ifname: the interface name
|
|
|
|
* @tapfd: file descriptor return value for the new tap device
|
2012-03-01 20:35:30 +00:00
|
|
|
* @flags: OR of virNetDevTapCreateFlags. Only one flag is recognized:
|
|
|
|
*
|
|
|
|
* VIR_NETDEV_TAP_CREATE_VNET_HDR
|
|
|
|
* - Enable IFF_VNET_HDR on the tap device
|
Split bridge.h into three separate files
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
2011-11-02 13:41:58 +00:00
|
|
|
*
|
|
|
|
* 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
|
2012-03-01 20:35:30 +00:00
|
|
|
* persistent and closed. The caller must use virNetDevTapDelete to
|
|
|
|
* remove a persistent TAP devices when it is no longer needed.
|
Split bridge.h into three separate files
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
2011-11-02 13:41:58 +00:00
|
|
|
*
|
|
|
|
* Returns 0 in case of success or an errno code in case of failure.
|
|
|
|
*/
|
|
|
|
int virNetDevTapCreate(char **ifname,
|
2012-03-01 20:35:30 +00:00
|
|
|
int *tapfd,
|
2012-03-30 11:37:13 +00:00
|
|
|
unsigned int flags ATTRIBUTE_UNUSED)
|
Split bridge.h into three separate files
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
2011-11-02 13:41:58 +00:00
|
|
|
{
|
|
|
|
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
|
2012-03-01 20:35:30 +00:00
|
|
|
if ((flags & VIR_NETDEV_TAP_CREATE_VNET_HDR) &&
|
|
|
|
virNetDevProbeVnetHdr(fd))
|
Split bridge.h into three separate files
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
2011-11-02 13:41:58 +00:00
|
|
|
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,
|
2012-03-01 20:35:30 +00:00
|
|
|
int *tapfd ATTRIBUTE_UNUSED,
|
2012-03-30 11:37:13 +00:00
|
|
|
unsigned int flags ATTRIBUTE_UNUSED)
|
Split bridge.h into three separate files
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
2011-11-02 13:41:58 +00:00
|
|
|
{
|
|
|
|
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)
|
|
|
|
* @tapfd: file descriptor return value for the new tap device
|
2012-02-10 21:09:00 +00:00
|
|
|
* @virtPortProfile: bridge/port specific configuration
|
2012-03-01 20:35:30 +00:00
|
|
|
* @flags: OR of virNetDevTapCreateFlags:
|
|
|
|
|
|
|
|
* VIR_NETDEV_TAP_CREATE_IFUP
|
|
|
|
* - Bring the interface up
|
|
|
|
* VIR_NETDEV_TAP_CREATE_VNET_HDR
|
|
|
|
* - Enable IFF_VNET_HDR on the tap device
|
|
|
|
* VIR_NETDEV_TAP_CREATE_USE_MAC_FOR_BRIDGE
|
|
|
|
* - Set this interface's MAC as the bridge's MAC address
|
Split bridge.h into three separate files
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
2011-11-02 13:41:58 +00:00
|
|
|
*
|
|
|
|
* 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
|
2012-03-01 20:35:30 +00:00
|
|
|
* persistent and closed. The caller must use virNetDevTapDelete to remove
|
Split bridge.h into three separate files
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
2011-11-02 13:41:58 +00:00
|
|
|
* 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,
|
2012-03-07 07:15:36 +00:00
|
|
|
const unsigned char *vmuuid,
|
2012-02-10 21:09:00 +00:00
|
|
|
int *tapfd,
|
2012-03-01 20:35:30 +00:00
|
|
|
virNetDevVPortProfilePtr virtPortProfile,
|
|
|
|
unsigned int flags)
|
Split bridge.h into three separate files
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
2011-11-02 13:41:58 +00:00
|
|
|
{
|
util: centralize tap device MAC address 1st byte "0xFE" modification
When a tap device for a domain is created and attached to a bridge,
the first byte of the tap device MAC address is set to 0xFE, while the
rest is set to match the MAC address that will be presented to the
guest as its network device MAC address. Setting this high value in
the tap's MAC address discourages the bridge from using the tap
device's MAC address as the bridge's own MAC address (Linux bridges
always take on the lowest numbered MAC address of all attached devices
as their own).
In one case within libvirt, a tap device is created and attached to
the bridge with the intent that its MAC address be taken on by the
bridge as its own (this is used to assure that the bridge has a fixed
MAC address to prevent network outages created by the bridge MAC
address "flapping" as guests are started and stopped). In this case,
the first byte of the mac address is *not* altered to 0xFE.
In the current code, callers to virNetDevTapCreateInBridgePort each
make the MAC address modification themselves before calling, which
leads to code duplication, and also prevents lower level functions
from knowing the real MAC address being used by the guest. The problem
here is that openvswitch bridges must be informed about this MAC
address, or they will be unable to pass traffic to/from the guest.
This patch centralizes the location of the MAC address "0xFE fixup"
into virNetDevTapCreateInBridgePort(), meaning 1) callers of this
function no longer need the extra strange bit of code, and 2)
bitNetDevTapCreateBridgeInPort itself now is called with the guest's
unaltered MAC address, and can pass it on, unmodified, to
virNetDevOpenvswitchAddPort.
There is no other behavioral change created by this patch.
2012-02-16 23:49:57 +00:00
|
|
|
unsigned char tapmac[VIR_MAC_BUFLEN];
|
|
|
|
|
2012-03-01 20:35:30 +00:00
|
|
|
if (virNetDevTapCreate(ifname, tapfd, flags) < 0)
|
Split bridge.h into three separate files
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
2011-11-02 13:41:58 +00:00
|
|
|
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.
|
|
|
|
*/
|
util: centralize tap device MAC address 1st byte "0xFE" modification
When a tap device for a domain is created and attached to a bridge,
the first byte of the tap device MAC address is set to 0xFE, while the
rest is set to match the MAC address that will be presented to the
guest as its network device MAC address. Setting this high value in
the tap's MAC address discourages the bridge from using the tap
device's MAC address as the bridge's own MAC address (Linux bridges
always take on the lowest numbered MAC address of all attached devices
as their own).
In one case within libvirt, a tap device is created and attached to
the bridge with the intent that its MAC address be taken on by the
bridge as its own (this is used to assure that the bridge has a fixed
MAC address to prevent network outages created by the bridge MAC
address "flapping" as guests are started and stopped). In this case,
the first byte of the mac address is *not* altered to 0xFE.
In the current code, callers to virNetDevTapCreateInBridgePort each
make the MAC address modification themselves before calling, which
leads to code duplication, and also prevents lower level functions
from knowing the real MAC address being used by the guest. The problem
here is that openvswitch bridges must be informed about this MAC
address, or they will be unable to pass traffic to/from the guest.
This patch centralizes the location of the MAC address "0xFE fixup"
into virNetDevTapCreateInBridgePort(), meaning 1) callers of this
function no longer need the extra strange bit of code, and 2)
bitNetDevTapCreateBridgeInPort itself now is called with the guest's
unaltered MAC address, and can pass it on, unmodified, to
virNetDevOpenvswitchAddPort.
There is no other behavioral change created by this patch.
2012-02-16 23:49:57 +00:00
|
|
|
memcpy(tapmac, macaddr, VIR_MAC_BUFLEN);
|
2012-03-05 00:21:16 +00:00
|
|
|
if (!(flags & VIR_NETDEV_TAP_CREATE_USE_MAC_FOR_BRIDGE)) {
|
|
|
|
if (macaddr[0] == 0xFE) {
|
|
|
|
/* For normal use, the tap device's MAC address cannot
|
|
|
|
* match the MAC address used by the guest. This results
|
|
|
|
* in "received packet on vnetX with own address as source
|
|
|
|
* address" error logs from the kernel.
|
|
|
|
*/
|
|
|
|
virNetDevTapError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
"Unable to use MAC address starting with "
|
|
|
|
"reserved value 0xFE - '%02X:%02X:%02X:%02X:%02X:%02X' - ",
|
|
|
|
macaddr[0], macaddr[1], macaddr[2],
|
|
|
|
macaddr[3], macaddr[4], macaddr[5]);
|
|
|
|
goto error;
|
|
|
|
}
|
util: centralize tap device MAC address 1st byte "0xFE" modification
When a tap device for a domain is created and attached to a bridge,
the first byte of the tap device MAC address is set to 0xFE, while the
rest is set to match the MAC address that will be presented to the
guest as its network device MAC address. Setting this high value in
the tap's MAC address discourages the bridge from using the tap
device's MAC address as the bridge's own MAC address (Linux bridges
always take on the lowest numbered MAC address of all attached devices
as their own).
In one case within libvirt, a tap device is created and attached to
the bridge with the intent that its MAC address be taken on by the
bridge as its own (this is used to assure that the bridge has a fixed
MAC address to prevent network outages created by the bridge MAC
address "flapping" as guests are started and stopped). In this case,
the first byte of the mac address is *not* altered to 0xFE.
In the current code, callers to virNetDevTapCreateInBridgePort each
make the MAC address modification themselves before calling, which
leads to code duplication, and also prevents lower level functions
from knowing the real MAC address being used by the guest. The problem
here is that openvswitch bridges must be informed about this MAC
address, or they will be unable to pass traffic to/from the guest.
This patch centralizes the location of the MAC address "0xFE fixup"
into virNetDevTapCreateInBridgePort(), meaning 1) callers of this
function no longer need the extra strange bit of code, and 2)
bitNetDevTapCreateBridgeInPort itself now is called with the guest's
unaltered MAC address, and can pass it on, unmodified, to
virNetDevOpenvswitchAddPort.
There is no other behavioral change created by this patch.
2012-02-16 23:49:57 +00:00
|
|
|
tapmac[0] = 0xFE; /* Discourage bridge from using TAP dev MAC */
|
2012-03-05 00:21:16 +00:00
|
|
|
}
|
util: centralize tap device MAC address 1st byte "0xFE" modification
When a tap device for a domain is created and attached to a bridge,
the first byte of the tap device MAC address is set to 0xFE, while the
rest is set to match the MAC address that will be presented to the
guest as its network device MAC address. Setting this high value in
the tap's MAC address discourages the bridge from using the tap
device's MAC address as the bridge's own MAC address (Linux bridges
always take on the lowest numbered MAC address of all attached devices
as their own).
In one case within libvirt, a tap device is created and attached to
the bridge with the intent that its MAC address be taken on by the
bridge as its own (this is used to assure that the bridge has a fixed
MAC address to prevent network outages created by the bridge MAC
address "flapping" as guests are started and stopped). In this case,
the first byte of the mac address is *not* altered to 0xFE.
In the current code, callers to virNetDevTapCreateInBridgePort each
make the MAC address modification themselves before calling, which
leads to code duplication, and also prevents lower level functions
from knowing the real MAC address being used by the guest. The problem
here is that openvswitch bridges must be informed about this MAC
address, or they will be unable to pass traffic to/from the guest.
This patch centralizes the location of the MAC address "0xFE fixup"
into virNetDevTapCreateInBridgePort(), meaning 1) callers of this
function no longer need the extra strange bit of code, and 2)
bitNetDevTapCreateBridgeInPort itself now is called with the guest's
unaltered MAC address, and can pass it on, unmodified, to
virNetDevOpenvswitchAddPort.
There is no other behavioral change created by this patch.
2012-02-16 23:49:57 +00:00
|
|
|
|
|
|
|
if (virNetDevSetMAC(*ifname, tapmac) < 0)
|
Split bridge.h into three separate files
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
2011-11-02 13:41:58 +00:00
|
|
|
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;
|
|
|
|
|
2012-02-10 21:09:00 +00:00
|
|
|
if (virtPortProfile) {
|
2012-03-07 07:15:36 +00:00
|
|
|
if (virNetDevOpenvswitchAddPort(brname, *ifname, macaddr, vmuuid,
|
2012-02-10 21:09:00 +00:00
|
|
|
virtPortProfile) < 0) {
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (virNetDevBridgeAddPort(brname, *ifname) < 0)
|
|
|
|
goto error;
|
|
|
|
}
|
Split bridge.h into three separate files
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
2011-11-02 13:41:58 +00:00
|
|
|
|
2012-03-01 20:35:30 +00:00
|
|
|
if (virNetDevSetOnline(*ifname, !!(flags & VIR_NETDEV_TAP_CREATE_IFUP)) < 0)
|
Split bridge.h into three separate files
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
2011-11-02 13:41:58 +00:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
VIR_FORCE_CLOSE(*tapfd);
|
|
|
|
|
|
|
|
return errno;
|
|
|
|
}
|