On 3/3/2015 1:49 AM, Vasiliy Tolstov wrote:
2015-03-02 23:41 GMT+03:00 Brian Rak <brak(a)gameservers.com>:
> In IRC, I was directed to this patch:
>
https://www.redhat.com/archives/libvir-list/2015-February/msg01212.html ...
> which does exactly what I was looking for. It doesn't build cleanly in that
> state, but it's pretty trivial fix (needs actualType added to the function
> definition for qemuNetworkIfaceConnect and the two calls modified)
I send new patch version one day ago and it waiting for review.
We've been using this patch for a couple months now, and it's working
perfectly.
I noticed that it no longer applied cleanly against 1.2.14, so I updated it:
diff -urw src_clean/src/qemu/qemu_command.c src/src/qemu/qemu_command.c
--- src_clean/src/qemu/qemu_command.c 2015-03-26 22:01:44.000000000 -0400
+++ src/src/qemu/qemu_command.c 2015-04-21 11:34:03.363772741 -0400
@@ -330,10 +330,41 @@
return *tapfd < 0 ? -1 : 0;
}
+/**
+ * qemuExecuteEthernetScript:
+ * @ifname: the interface name
+ * @script: the script name
+ * This function executes script for new tap device created by libvirt.
+ * Returns 0 in case of success or -1 on failure
+ */
+static int qemuExecuteEthernetScript(const char *ifname, const char
*script)
+{
+ virCommandPtr cmd;
+ int ret;
+
+ cmd = virCommandNew(script);
+ virCommandAddArgFormat(cmd, "%s", ifname);
+ virCommandClearCaps(cmd);
+#ifdef CAP_NET_ADMIN
+ virCommandAllowCap(cmd, CAP_NET_ADMIN);
+#endif
+ virCommandAddEnvPassCommon(cmd);
+
+ if (virCommandRun(cmd, NULL) < 0) {
+ ret = -1;
+ } else {
+ ret = 0;
+ }
+
+ virCommandFree(cmd);
+ return ret;
+}
+
/* qemuNetworkIfaceConnect - *only* called if actualType is
- * VIR_DOMAIN_NET_TYPE_NETWORK or VIR_DOMAIN_NET_TYPE_BRIDGE (i.e. if
- * the connection is made with a tap device connecting to a bridge
- * device)
+ * VIR_DOMAIN_NET_TYPE_NETWORK, VIR_DOMAIN_NET_TYPE_BRIDGE or
+ * VIR_DOMAIN_NET_TYPE_ETHERNET (i.e. if the connection is
+ * made with a tap device connecting to a bridge device or
+ * used ethernet tap device)
*/
int
qemuNetworkIfaceConnect(virDomainDefPtr def,
@@ -341,7 +372,8 @@
virDomainNetDefPtr net,
virQEMUCapsPtr qemuCaps,
int *tapfd,
- size_t *tapfdSize)
+ size_t *tapfdSize,
+ int actualType)
{
const char *brname;
int ret = -1;
@@ -359,11 +391,6 @@
}
}
- if (!(brname = virDomainNetGetActualBridgeName(net))) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing bridge
name"));
- goto cleanup;
- }
-
if (!net->ifname ||
STRPREFIX(net->ifname, VIR_NET_GENERATED_PREFIX) ||
strchr(net->ifname, '%')) {
@@ -379,6 +406,22 @@
tap_create_flags |= VIR_NETDEV_TAP_CREATE_VNET_HDR;
}
+ if (actualType == VIR_DOMAIN_NET_TYPE_ETHERNET) {
+ if (virNetDevTapCreate(&net->ifname, tunpath, tapfd, *tapfdSize,
+ tap_create_flags) < 0) {
+ virDomainAuditNetDevice(def, net, tunpath, false);
+ goto cleanup;
+ }
+ if (net->script) {
+ if (qemuExecuteEthernetScript(net->ifname, net->script) < 0)
+ goto cleanup;
+ }
+ } else {
+ if (!(brname = virDomainNetGetActualBridgeName(net))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing
bridge name"));
+ goto cleanup;
+ }
+
if (cfg->privileged) {
if (virNetDevTapCreateInBridgePort(brname, &net->ifname,
&net->mac,
def->uuid, tunpath, tapfd,
*tapfdSize,
@@ -415,8 +458,8 @@
*tapfdSize = 1;
}
}
-
virDomainAuditNetDevice(def, net, tunpath, true);
+ }
if (cfg->macFilter &&
ebtablesAddForwardAllowIn(driver->ebtables,
@@ -5123,6 +5166,7 @@
case VIR_DOMAIN_NET_TYPE_BRIDGE:
case VIR_DOMAIN_NET_TYPE_NETWORK:
case VIR_DOMAIN_NET_TYPE_DIRECT:
+ case VIR_DOMAIN_NET_TYPE_ETHERNET:
virBufferAsprintf(&buf, "tap%c", type_sep);
/* for one tapfd 'fd=' shall be used,
* for more than one 'fds=' is the right choice */
@@ -5140,20 +5184,6 @@
is_tap = true;
break;
- case VIR_DOMAIN_NET_TYPE_ETHERNET:
- virBufferAddLit(&buf, "tap");
- if (net->ifname) {
- virBufferAsprintf(&buf, "%cifname=%s", type_sep,
net->ifname);
- type_sep = ',';
- }
- if (net->script) {
- virBufferAsprintf(&buf, "%cscript=%s", type_sep,
- net->script);
- type_sep = ',';
- }
- is_tap = true;
- break;
-
case VIR_DOMAIN_NET_TYPE_CLIENT:
virBufferAsprintf(&buf, "socket%cconnect=%s:%d",
type_sep,
@@ -8009,7 +8039,8 @@
/* Currently nothing besides TAP devices supports multiqueue. */
if (net->driver.virtio.queues > 0 &&
!(actualType == VIR_DOMAIN_NET_TYPE_NETWORK ||
- actualType == VIR_DOMAIN_NET_TYPE_BRIDGE)) {
+ actualType == VIR_DOMAIN_NET_TYPE_BRIDGE ||
+ actualType == VIR_DOMAIN_NET_TYPE_ETHERNET)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Multiqueue network is not supported for: %s"),
virDomainNetTypeToString(actualType));
@@ -8026,7 +8057,8 @@
}
if (actualType == VIR_DOMAIN_NET_TYPE_NETWORK ||
- actualType == VIR_DOMAIN_NET_TYPE_BRIDGE) {
+ actualType == VIR_DOMAIN_NET_TYPE_BRIDGE ||
+ actualType == VIR_DOMAIN_NET_TYPE_ETHERNET) {
tapfdSize = net->driver.virtio.queues;
if (!tapfdSize)
tapfdSize = 1;
@@ -8039,7 +8071,7 @@
if (qemuNetworkIfaceConnect(def, driver, net,
qemuCaps, tapfd,
- &tapfdSize) < 0)
+ &tapfdSize, actualType) < 0)
goto cleanup;
} else if (actualType == VIR_DOMAIN_NET_TYPE_DIRECT) {
if (VIR_ALLOC(tapfd) < 0 || VIR_ALLOC(tapfdName) < 0)
diff -urw src_clean/src/qemu/qemu_command.h src/src/qemu/qemu_command.h
--- src_clean/src/qemu/qemu_command.h 2015-03-25 03:36:59.000000000 -0400
+++ src/src/qemu/qemu_command.h 2015-04-21 11:33:26.557397006 -0400
@@ -223,7 +223,8 @@
virDomainNetDefPtr net,
virQEMUCapsPtr qemuCaps,
int *tapfd,
- size_t *tapfdSize)
+ size_t *tapfdSize,
+ int qemuNetworkIfaceConnect)
ATTRIBUTE_NONNULL(2);
int qemuPhysIfaceConnect(virDomainDefPtr def,
Only in src/src/qemu: qemu_command.h.orig
diff -urw src_clean/src/qemu/qemu_hotplug.c src/src/qemu/qemu_hotplug.c
--- src_clean/src/qemu/qemu_hotplug.c 2015-03-25 03:36:59.000000000 -0400
+++ src/src/qemu/qemu_hotplug.c 2015-04-21 11:34:34.810243144 -0400
@@ -898,7 +898,8 @@
/* Currently nothing besides TAP devices supports multiqueue. */
if (net->driver.virtio.queues > 0 &&
!(actualType == VIR_DOMAIN_NET_TYPE_NETWORK ||
- actualType == VIR_DOMAIN_NET_TYPE_BRIDGE)) {
+ actualType == VIR_DOMAIN_NET_TYPE_BRIDGE ||
+ actualType == VIR_DOMAIN_NET_TYPE_ETHERNET)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Multiqueue network is not supported for: %s"),
virDomainNetTypeToString(actualType));
@@ -906,7 +907,8 @@
}
if (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE ||
- actualType == VIR_DOMAIN_NET_TYPE_NETWORK) {
+ actualType == VIR_DOMAIN_NET_TYPE_NETWORK ||
+ actualType == VIR_DOMAIN_NET_TYPE_ETHERNET) {
tapfdSize = vhostfdSize = net->driver.virtio.queues;
if (!tapfdSize)
tapfdSize = vhostfdSize = 1;
@@ -917,7 +919,7 @@
goto cleanup;
memset(vhostfd, -1, sizeof(*vhostfd) * vhostfdSize);
if (qemuNetworkIfaceConnect(vm->def, driver, net,
- priv->qemuCaps, tapfd, &tapfdSize) < 0)
+ priv->qemuCaps, tapfd, &tapfdSize,
actualType) < 0)
goto cleanup;
iface_connected = true;
if (qemuOpenVhostNet(vm->def, net, priv->qemuCaps, vhostfd,
&vhostfdSize) < 0)
@@ -937,13 +939,6 @@
iface_connected = true;
if (qemuOpenVhostNet(vm->def, net, priv->qemuCaps, vhostfd,
&vhostfdSize) < 0)
goto cleanup;
- } else if (actualType == VIR_DOMAIN_NET_TYPE_ETHERNET) {
- vhostfdSize = 1;
- if (VIR_ALLOC(vhostfd) < 0)
- goto cleanup;
- *vhostfd = -1;
- if (qemuOpenVhostNet(vm->def, net, priv->qemuCaps, vhostfd,
&vhostfdSize) < 0)
- goto cleanup;
}
/* Set device online immediately */
diff -urw src_clean/src/qemu/qemu_process.c src/src/qemu/qemu_process.c
--- src_clean/src/qemu/qemu_process.c 2015-03-30 20:36:17.000000000 -0400
+++ src/src/qemu/qemu_process.c 2015-04-21 11:33:26.559396972 -0400
@@ -5248,6 +5248,12 @@
cfg->stateDir));
VIR_FREE(net->ifname);
break;
+ case VIR_DOMAIN_NET_TYPE_ETHERNET:
+ if (net->ifname) {
+ ignore_value(virNetDevTapDelete(net->ifname,
net->backend.tap));
+ VIR_FREE(net->ifname);
+ }
+ break;
case VIR_DOMAIN_NET_TYPE_BRIDGE:
case VIR_DOMAIN_NET_TYPE_NETWORK:
#ifdef VIR_NETDEV_TAP_REQUIRE_MANUAL_CLEANUP