From: Marc-André Lureau <marcandre.lureau(a)redhat.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau(a)redhat.com>
---
src/qemu/qemu_hotplug.c | 33 ++++++++++++++++++++++++++++++---
src/qemu/qemu_monitor.c | 13 ++++++++++---
src/qemu/qemu_monitor.h | 3 ++-
3 files changed, 42 insertions(+), 7 deletions(-)
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 43c3f0755b..fcbf7a8aa9 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -1136,6 +1136,7 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_NET, { .net = net } };
virErrorPtr originalError = NULL;
VIR_AUTOFREE(char *) slirpfdName = NULL;
+ int slirpfd = -1;
char **tapfdName = NULL;
int *tapfd = NULL;
size_t tapfdSize = 0;
@@ -1315,7 +1316,26 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
break;
case VIR_DOMAIN_NET_TYPE_USER:
- /* No preparation needed. */
+ if (!priv->disableSlirp &&
+ virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_NET_SOCKET_DGRAM)) {
+ qemuSlirpPtr slirp = qemuInterfacePrepareSlirp(driver, net);
+
+ if (!slirp)
+ break;
+
+ QEMU_DOMAIN_NETWORK_PRIVATE(net)->slirp = slirp;
+
+ if (qemuSlirpOpen(slirp, driver, vm->def) < 0 ||
+ qemuSlirpStart(slirp, vm, driver, net, true, NULL) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("Failed to start slirp"));
+ goto cleanup;
+ }
+
+ slirpfd = qemuSlirpGetFD(slirp);
+ if (virAsprintf(&slirpfdName, "slirpfd-%s", net->info.alias)
< 0)
+ goto cleanup;
+ }
break;
case VIR_DOMAIN_NET_TYPE_SERVER:
@@ -1391,7 +1411,8 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
if (qemuMonitorAddNetdev(priv->mon, netstr,
tapfd, tapfdName, tapfdSize,
- vhostfd, vhostfdName, vhostfdSize) < 0) {
+ vhostfd, vhostfdName, vhostfdSize,
+ slirpfd, slirpfdName) < 0) {
ignore_value(qemuDomainObjExitMonitor(driver, vm));
virDomainAuditNet(vm, NULL, net, "attach", false);
goto try_remove;
@@ -1506,6 +1527,7 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
VIR_FREE(charDevAlias);
virObjectUnref(conn);
virDomainCCWAddressSetFree(ccwaddrs);
+ VIR_FORCE_CLOSE(slirpfd);
return ret;
@@ -1516,6 +1538,8 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
virErrorPreserveLast(&originalError);
if (virAsprintf(&netdev_name, "host%s", net->info.alias) >= 0) {
qemuDomainObjEnterMonitor(driver, vm);
+ if (QEMU_DOMAIN_NETWORK_PRIVATE(net)->slirp)
+ qemuSlirpStop(QEMU_DOMAIN_NETWORK_PRIVATE(net)->slirp, vm, driver, net,
true);
if (charDevPlugged &&
qemuMonitorDetachCharDev(priv->mon, charDevAlias) < 0)
VIR_WARN("Failed to remove associated chardev %s", charDevAlias);
@@ -2201,7 +2225,7 @@ int qemuDomainAttachChrDevice(virQEMUDriverPtr driver,
if (guestfwd) {
if (qemuMonitorAddNetdev(priv->mon, devstr,
- NULL, NULL, 0, NULL, NULL, 0) < 0)
+ NULL, NULL, 0, NULL, NULL, 0, -1, NULL) < 0)
goto exit_monitor;
} else {
if (qemuMonitorAddDevice(priv->mon, devstr) < 0)
@@ -4674,6 +4698,9 @@ qemuDomainRemoveNetDevice(virQEMUDriverPtr driver,
if (qemuDomainObjExitMonitor(driver, vm) < 0)
goto cleanup;
+ if (QEMU_DOMAIN_NETWORK_PRIVATE(net)->slirp)
+ qemuSlirpStop(QEMU_DOMAIN_NETWORK_PRIVATE(net)->slirp, vm, driver, net,
true);
+
virDomainAuditNet(vm, net, NULL, "detach", true);
for (i = 0; i < vm->def->nnets; i++) {
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index a880da3ab6..84af24958a 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -2844,15 +2844,17 @@ int
qemuMonitorAddNetdev(qemuMonitorPtr mon,
const char *netdevstr,
int *tapfd, char **tapfdName, int tapfdSize,
- int *vhostfd, char **vhostfdName, int vhostfdSize)
+ int *vhostfd, char **vhostfdName, int vhostfdSize,
+ int slirpfd, char *slirpfdName)
{
int ret = -1;
size_t i = 0, j = 0;
VIR_DEBUG("netdevstr=%s tapfd=%p tapfdName=%p tapfdSize=%d"
- "vhostfd=%p vhostfdName=%p vhostfdSize=%d",
+ "vhostfd=%p vhostfdName=%p vhostfdSize=%d"
+ "slirpfd=%d slirpfdName=%s",
netdevstr, tapfd, tapfdName, tapfdSize,
- vhostfd, vhostfdName, vhostfdSize);
+ vhostfd, vhostfdName, vhostfdSize, slirpfd, slirpfdName);
QEMU_CHECK_MONITOR(mon);
@@ -2865,6 +2867,11 @@ qemuMonitorAddNetdev(qemuMonitorPtr mon,
goto cleanup;
}
+ if (slirpfd != -1) {
+ if (qemuMonitorSendFileHandle(mon, slirpfdName, slirpfd) < 0)
+ goto cleanup;
+ }
+
ret = qemuMonitorJSONAddNetdev(mon, netdevstr);
cleanup:
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 88c9702530..c675865e3f 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -880,7 +880,8 @@ int qemuMonitorRemoveFd(qemuMonitorPtr mon, int fdset, int fd);
int qemuMonitorAddNetdev(qemuMonitorPtr mon,
const char *netdevstr,
int *tapfd, char **tapfdName, int tapfdSize,
- int *vhostfd, char **vhostfdName, int vhostfdSize);
+ int *vhostfd, char **vhostfdName, int vhostfdSize,
+ int slirpfd, char *slirpfdName);
int qemuMonitorRemoveNetdev(qemuMonitorPtr mon,
const char *alias);
--
2.23.0.rc1