On 09/20/2011 05:18 PM, Tyler Coumbes wrote:
Update code to create generic ethernet interfaces using the new
utility library tunctl making
changes to create the TAP device in libvirt and pass it to qemu as a
file descriptor.
This patch doesn't refactor src/util/bridge.c either, which means that
if applied, we would have two copies of very similar code in two
different files - that's a maintenance nightmare. We'll definitely need
a v2 patch series that refactors things with minimal duplication.
Or, can this patch directly use the existing br* interfaces, instead of
introducing a new file in patch 1/2?
---
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index ee4b52b..181f56c 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -396,6 +396,51 @@ qemuOpenVhostNet(virDomainDefPtr def,
}
+int qemuEthernetIfaceCreate(virDomainDefPtr def,
+ virDomainNetDefPtr net,
+ virBitmapPtr qemuCaps)
+{
+ int tapfd;
+ int err;
+ int vnet_hdr = 0;
+ unsigned char tapmac[VIR_MAC_BUFLEN];
+
+ if (qemuCapsGet(qemuCaps, QEMU_CAPS_VNET_HDR)&&
+ net->model&& STREQ(net->model, "virtio"))
+ vnet_hdr = 1;
+
+ if (!net->ifname ||
+ STRPREFIX(net->ifname, "vnet") ||
+ strchr(net->ifname, '%')) {
+ VIR_FREE(net->ifname);
+ if (!(net->ifname = strdup("vnet%d"))) {
+ virReportOOMError();
+ return -1;
+ }
+ }
+
+ err = createTap(&net->ifname, vnet_hdr,&tapfd);
+ virDomainAuditNetDevice(def, net, "/dev/net/tun", tapfd>= 0);
+ if (tapfd< 0 || err)
+ return -1;
+
+ memcpy(tapmac, net->mac, VIR_MAC_BUFLEN);
+ /* Discourage bridge from using TAP dev MAC */
+ tapmac[0] = 0xFE;
+ err = tapSetInterfaceMac(net->ifname, tapmac);
+
+ if (err)
+ return -1;
This leaks tapfd. Our style tends to use 'goto error' to ensure that
all cleanup occurs at the end, rather than 'return' in the middle of a
function.
+
+ err = tapSetInterfaceUp(net->ifname, 1);
+
+ if (err)
+ return -1;
+
+ return tapfd;
+}
+
+
static int qemuDomainDeviceAliasIndex(virDomainDeviceInfoPtr info,
const char *prefix)
@@ -4064,6 +4112,18 @@ qemuBuildCommandLine(virConnectPtr conn,
if (snprintf(tapfd_name, sizeof(tapfd_name), "%d",
tapfd)>= sizeof(tapfd_name))
goto no_memory;
+ } else if (actualType == VIR_DOMAIN_NET_TYPE_ETHERNET&&
+ !net->data.ethernet.script) {
+ int tapfd = qemuEthernetIfaceCreate(def, net, qemuCaps);
+ if (tapfd< 0)
+ goto error;
+
+ last_good_net = i;
+ virCommandTransferFD(cmd, tapfd);
Check for failure to transfer the fd, and abort the command in that case
(hmm, that's a pre-existing problem with the other fd transfers in this
function).
--
Eric Blake eblake(a)redhat.com +1-801-349-2682
Libvirt virtualization library
http://libvirt.org