[libvirt] [PATCH] Fix compile error for stable 1.2.9
by Yang hongyang
Seems a backport miss. An extra member is passed to struct
virLXCBasicMountInfo.
Signed-off-by: Yang hongyang <hongyang.yang(a)easystack.cn>
---
src/lxc/lxc_container.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index 28dabec..1c65fa9 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -760,7 +760,7 @@ typedef struct {
static const virLXCBasicMountInfo lxcBasicMounts[] = {
{ "proc", "/proc", "proc", MS_NOSUID|MS_NOEXEC|MS_NODEV, false, false },
- { "/proc/sys", "/proc/sys", NULL, MS_BIND|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RDONLY, false, false, false },
+ { "/proc/sys", "/proc/sys", NULL, MS_BIND|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RDONLY, false, false },
{ "sysfs", "/sys", "sysfs", MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RDONLY, false, false },
{ "securityfs", "/sys/kernel/security", "securityfs", MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RDONLY, true, true },
#if WITH_SELINUX
--
1.7.1
11 months, 2 weeks
[libvirt] Supporting vhost-net and macvtap in libvirt for QEMU
by Anthony Liguori
Disclaimer: I am neither an SR-IOV nor a vhost-net expert, but I've CC'd
people that are who can throw tomatoes at me for getting bits wrong :-)
I wanted to start a discussion about supporting vhost-net in libvirt.
vhost-net has not yet been merged into qemu but I expect it will be soon
so it's a good time to start this discussion.
There are two modes worth supporting for vhost-net in libvirt. The
first mode is where vhost-net backs to a tun/tap device. This is
behaves in very much the same way that -net tap behaves in qemu today.
Basically, the difference is that the virtio backend is in the kernel
instead of in qemu so there should be some performance improvement.
Current, libvirt invokes qemu with -net tap,fd=X where X is an already
open fd to a tun/tap device. I suspect that after we merge vhost-net,
libvirt could support vhost-net in this mode by just doing -net
vhost,fd=X. I think the only real question for libvirt is whether to
provide a user visible switch to use vhost or to just always use vhost
when it's available and it makes sense. Personally, I think the later
makes sense.
The more interesting invocation of vhost-net though is one where the
vhost-net device backs directly to a physical network card. In this
mode, vhost should get considerably better performance than the current
implementation. I don't know the syntax yet, but I think it's
reasonable to assume that it will look something like -net
tap,dev=eth0. The effect will be that eth0 is dedicated to the guest.
On most modern systems, there is a small number of network devices so
this model is not all that useful except when dealing with SR-IOV
adapters. In that case, each physical device can be exposed as many
virtual devices (VFs). There are a few restrictions here though. The
biggest is that currently, you can only change the number of VFs by
reloading a kernel module so it's really a parameter that must be set at
startup time.
I think there are a few ways libvirt could support vhost-net in this
second mode. The simplest would be to introduce a new tag similar to
<source network='br0'>. In fact, if you probed the device type for the
network parameter, you could probably do something like <source
network='eth0'> and have it Just Work.
Another model would be to have libvirt see an SR-IOV adapter as a
network pool whereas it handled all of the VF management. Considering
how inflexible SR-IOV is today, I'm not sure whether this is the best model.
Has anyone put any more thought into this problem or how this should be
modeled in libvirt? Michael, could you share your current thinking for
-net syntax?
--
Regards,
Anthony Liguori
11 months, 2 weeks
[libvirt] [PATCH] qemu: Use iohelper during restore
by Shivaprasad G Bhat
Commit afe6e58 & c4caab53 made necessary changes to use io-helpers
during save and restore. The commit c4caab53 missed to remove the
redundant check in qemuDomainSaveImageOpen() because of which
virFileWrapperFdNew() is not called if bypass_cache is false.
Signed-off-by: Shivaprasad G Bhat <sbhat(a)linux.vnet.ibm.com>
---
src/qemu/qemu_driver.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 516a851..ac89372 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -6150,9 +6150,11 @@ qemuDomainSaveImageOpen(virQEMUDriverPtr driver,
virDomainDefPtr def = NULL;
int oflags = open_write ? O_RDWR : O_RDONLY;
virCapsPtr caps = NULL;
+ unsigned int wrapperFlags = VIR_FILE_WRAPPER_NON_BLOCKING;
if (bypass_cache) {
int directFlag = virFileDirectFdFlag();
+ wrapperFlags |= VIR_FILE_WRAPPER_BYPASS_CACHE;
if (directFlag < 0) {
virReportError(VIR_ERR_OPERATION_FAILED, "%s",
_("bypass cache unsupported by this system"));
@@ -6166,9 +6168,8 @@ qemuDomainSaveImageOpen(virQEMUDriverPtr driver,
if ((fd = qemuOpenFile(driver, NULL, path, oflags, NULL, NULL)) < 0)
goto error;
- if (bypass_cache &&
- !(*wrapperFd = virFileWrapperFdNew(&fd, path,
- VIR_FILE_WRAPPER_BYPASS_CACHE)))
+ if (wrapperFd &&
+ !(*wrapperFd = virFileWrapperFdNew(&fd, path, wrapperFlags)))
goto error;
if (saferead(fd, &header, sizeof(header)) != sizeof(header)) {
7 years, 3 months
[libvirt] [PATCH] qemu: fix crash on getting block stats for empty cdrom
by Nikolay Shirokovskiy
Looks like it was introduced in c5f61513. Before this commit handling empty cdrom
was correct becase physical sizes of non block disks are not updated.
Now when all types are supported we need to check for empty drives.
[1] crash backtrace
0 __strrchr_sse42 () at ../sysdeps/x86_64/multiarch/strrchr.S:138
1 0x00007ffff7242192 in virFileIsSharedFSType (path=0x0, fstypes=63) at util/virfile.c:3351
2 0x00007ffff7242a5b in virFileIsSharedFS (path=0x0) at util/virfile.c:3557
3 0x00007fffdb835443 in qemuOpenFileAs (fallback_uid=0, fallback_gid=107, dynamicOwnership=true, path=0x0,
oflags=0, needUnlink=0x0, bypassSecurityDriver=0x0) at qemu/qemu_driver.c:2927
4 0x00007fffdb83539b in qemuOpenFile (driver=0x7fffcc1062f0, vm=0x7fffcc25aa50, path=0x0, oflags=0,
needUnlink=0x0, bypassSecurityDriver=0x0) at qemu/qemu_driver.c:2908
5 0x00007fffdb84d2d3 in qemuDomainStorageOpenStat (driver=0x7fffcc1062f0, cfg=0x7fffcc188880, vm=0x7fffcc25aa50,
src=0x7fffcc256920, ret_fd=0x7fffe6a49488, ret_sb=0x7fffe6a49490) at qemu/qemu_driver.c:11266
6 0x00007fffdb84d4ff in qemuDomainStorageUpdatePhysical (driver=0x7fffcc1062f0, cfg=0x7fffcc188880,
vm=0x7fffcc25aa50, src=0x7fffcc256920) at qemu/qemu_driver.c:11319
7 0x00007fffdb8661e7 in qemuDomainGetStatsOneBlock (driver=0x7fffcc1062f0, cfg=0x7fffcc188880, dom=0x7fffcc25aa50,
record=0x7fffa8000e70, maxparams=0x7fffe6a49790, disk=0x7fffcc2565a0, src=0x7fffcc256920, block_idx=7,
backing_idx=0, stats=0x7fffa8000e90) at qemu/qemu_driver.c:19223
8 0x00007fffdb86652b in qemuDomainGetStatsBlock (driver=0x7fffcc1062f0, dom=0x7fffcc25aa50, record=0x7fffa8000e70,
maxparams=0x7fffe6a49790, privflags=1) at qemu/qemu_driver.c:19282
9 0x00007fffdb8669f7 in qemuDomainGetStats (conn=0x7fffb80009a0, dom=0x7fffcc25aa50, stats=127,
record=0x7fffe6a49870, flags=1) at qemu/qemu_driver.c:19444
10 0x00007fffdb866dc8 in qemuConnectGetAllDomainStats (conn=0x7fffb80009a0, doms=0x0, ndoms=0, stats=127,
retStats=0x7fffe6a499a0, flags=1) at qemu/qemu_driver.c:19534
11 0x00007ffff7388376 in virConnectGetAllDomainStats (conn=0x7fffb80009a0, stats=0, retStats=0x7fffe6a499a0,
flags=1) at libvirt-domain.c:11311
---
src/qemu/qemu_driver.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index bc5e448..16b435a 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -19170,6 +19170,7 @@ qemuDomainGetStatsOneBlock(virQEMUDriverPtr driver,
QEMU_ADD_NAME_PARAM(record, maxparams, "block", "name", block_idx,
disk->dst);
+
if (virStorageSourceIsLocalStorage(src) && src->path)
QEMU_ADD_NAME_PARAM(record, maxparams, "block", "path",
block_idx, src->path);
@@ -19216,7 +19217,7 @@ qemuDomainGetStatsOneBlock(virQEMUDriverPtr driver,
if (entry->capacity)
QEMU_ADD_BLOCK_PARAM_ULL(record, maxparams, block_idx,
"capacity", entry->capacity);
- if (entry->physical) {
+ if (entry->physical || virStorageSourceIsEmpty(src)) {
QEMU_ADD_BLOCK_PARAM_ULL(record, maxparams, block_idx,
"physical", entry->physical);
} else {
--
1.8.3.1
7 years, 5 months
[libvirt] [PATCH] leasetime support per <dhcp> and <host>
by Alberto Ruiz
Support for custom dhcp wide and per host leasetime.
It is specified as a child tag for <dhcp>:
<dhcp>
<leasetime>24h</leasetime>
...
</dhcp>
And as an attribute for <host>:
<dhcp>
<host leasetime="7d" .../>
</dhcp>
These are the different notations:
-1 (infinite/unlimited lease)
120 (seconds are the default unit, 120 seconds is the minimum, if less is
specified it will use 120)
300s (seconds)
5m (minutes)
24h (hours)
7d (days)
---
docs/schemas/basictypes.rng | 5 +
docs/schemas/network.rng | 8 ++
src/conf/network_conf.c | 86 +++++++++++++-
src/conf/network_conf.h | 4 +-
src/libvirt_private.syms | 1 +
src/network/bridge_driver.c | 132
+++++++++++++++++----
src/network/bridge_driver.h | 1 +
src/util/virdnsmasq.c | 106 +++++++++++------
src/util/virdnsmasq.h | 2 +
.../dhcp6-nat-network.hostsfile | 7 ++
tests/networkxml2confdata/dhcp6-network.hostsfile | 5 +
.../dhcp6host-routed-network.hostsfile | 7 ++
tests/networkxml2confdata/leasetime-days.conf | 17 +++
tests/networkxml2confdata/leasetime-days.xml | 18 +++
tests/networkxml2confdata/leasetime-host.conf | 16 +++
tests/networkxml2confdata/leasetime-host.hostsfile | 6 +
tests/networkxml2confdata/leasetime-host.xml | 22 ++++
tests/networkxml2confdata/leasetime-hours.conf | 17 +++
tests/networkxml2confdata/leasetime-hours.xml | 18 +++
tests/networkxml2confdata/leasetime-infinite.conf | 17 +++
tests/networkxml2confdata/leasetime-infinite.xml | 18 +++
tests/networkxml2confdata/leasetime-minutes.conf | 17 +++
tests/networkxml2confdata/leasetime-minutes.xml | 18 +++
tests/networkxml2confdata/leasetime-seconds.conf | 17 +++
tests/networkxml2confdata/leasetime-seconds.xml | 18 +++
tests/networkxml2confdata/leasetime.conf | 17 +++
tests/networkxml2confdata/leasetime.xml | 18 +++
.../nat-network-dns-srv-record-minimal.hostsfile | 2 +
.../nat-network-dns-srv-record.hostsfile | 2 +
.../nat-network-dns-txt-record.hostsfile | 2 +
.../nat-network-name-with-quotes.hostsfile | 2 +
tests/networkxml2confdata/nat-network.hostsfile | 2 +
tests/networkxml2conftest.c | 47 ++++++--
33 files changed, 597 insertions(+), 78 deletions(-)
create mode 100644 tests/networkxml2confdata/dhcp6-nat-network.hostsfile
create mode 100644 tests/networkxml2confdata/dhcp6-network.hostsfile
create mode 100644 tests/networkxml2confdata/dhcp6host-routed-network.
hostsfile
create mode 100644 tests/networkxml2confdata/leasetime-days.conf
create mode 100644 tests/networkxml2confdata/leasetime-days.xml
create mode 100644 tests/networkxml2confdata/leasetime-host.conf
create mode 100644 tests/networkxml2confdata/leasetime-host.hostsfile
create mode 100644 tests/networkxml2confdata/leasetime-host.xml
create mode 100644 tests/networkxml2confdata/leasetime-hours.conf
create mode 100644 tests/networkxml2confdata/leasetime-hours.xml
create mode 100644 tests/networkxml2confdata/leasetime-infinite.conf
create mode 100644 tests/networkxml2confdata/leasetime-infinite.xml
create mode 100644 tests/networkxml2confdata/leasetime-minutes.conf
create mode 100644 tests/networkxml2confdata/leasetime-minutes.xml
create mode 100644 tests/networkxml2confdata/leasetime-seconds.conf
create mode 100644 tests/networkxml2confdata/leasetime-seconds.xml
create mode 100644 tests/networkxml2confdata/leasetime.conf
create mode 100644 tests/networkxml2confdata/leasetime.xml
create mode 100644 tests/networkxml2confdata/nat-network-dns-srv-record-
minimal.hostsfile
create mode 100644 tests/networkxml2confdata/nat-network-dns-srv-record.
hostsfile
create mode 100644 tests/networkxml2confdata/nat-network-dns-txt-record.
hostsfile
create mode 100644 tests/networkxml2confdata/nat-network-name-with-quotes.
hostsfile
create mode 100644 tests/networkxml2confdata/nat-network.hostsfile
diff --git a/docs/schemas/basictypes.rng b/docs/schemas/basictypes.rng
index 1b4f980..11fbe2b 100644
--- a/docs/schemas/basictypes.rng
+++ b/docs/schemas/basictypes.rng
@@ -518,4 +518,9 @@
</element>
</define>
+ <define name="leaseTime">
+ <data type="string">
+ <param name="pattern">-?[0-9]*[smhd]?</param>
+ </data>
+ </define>
</grammar>
diff --git a/docs/schemas/network.rng b/docs/schemas/network.rng
index 1a18e64..e6ddb63 100644
--- a/docs/schemas/network.rng
+++ b/docs/schemas/network.rng
@@ -340,6 +340,11 @@
<!-- Define the range(s) of IP addresses that the DHCP
server should hand out -->
<element name="dhcp">
+ <optional>
+ <element name="leasetime">
+ <ref name="leaseTime"/>
+ </element>
+ </optional>
<zeroOrMore>
<element name="range">
<attribute name="start"><ref
name="ipAddr"/></attribute>
@@ -361,6 +366,9 @@
<attribute name="name"><text/></attribute>
</choice>
<attribute name="ip"><ref name="ipAddr"/></attribute>
+ <optional>
+ <attribute name="leasetime"><ref
name="leaseTime"/></attribute>
+ </optional>
</element>
</zeroOrMore>
<optional>
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index aa39776..bcc4bbb 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -30,6 +30,8 @@
#include <fcntl.h>
#include <string.h>
#include <dirent.h>
+#include <stdlib.h>
+#include <inttypes.h>
#include "virerror.h"
#include "datatypes.h"
@@ -911,16 +913,83 @@ virSocketAddrRangeParseXML(const char *networkName,
return ret;
}
+static int64_t
+virNetworkDHCPDefGetLeaseTime (xmlNodePtr node,
+ xmlXPathContextPtr ctxt,
+ const char* query,
+ bool *error)
+{
+ int64_t multiplier = 1, result = -1;
+ char *leaseString;
+ xmlNodePtr save;
+ size_t len;
+
+ *error = 0;
+
+ save = ctxt->node;
+ ctxt->node = node;
+
+ leaseString = virXPathString (query, ctxt);
+
+ /* If value is not present we set the value to -2 */
+ if (leaseString == NULL) {
+ result = -2;
+ goto cleanup;
+ }
+
+ len = strlen (leaseString) - 1;
+
+ if (leaseString[len] == 'm')
+ multiplier = 60;
+ else if (leaseString[len] == 'h')
+ multiplier = 60 * 60;
+ else if (leaseString[len] == 'd')
+ multiplier = 60 * 60 * 24;
+
+ /* Remove the time unit suffix */
+ if (leaseString[len] < 48 || leaseString[len] > 57)
+ leaseString[len] = '\0';
+
+ errno = 0;
+ result = (int64_t) strtoll((const char*)leaseString, NULL, 10);
+
+ /* Report any errors parsing the string */
+ if (errno != 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("<leasetime> value could not be converted to a
signed integer: %s"),
+ leaseString);
+ *error = 1;
+ goto cleanup;
+ }
+
+ result = result * multiplier;
+
+ if (result > UINT32_MAX || result < -1) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("<leasetime> value cannot be greater than the
equivalent of %" PRIo32 " seconds or less than -1: %" PRId64),
+ UINT32_MAX, result);
+ *error = 1;
+ }
+
+cleanup:
+ VIR_FREE(leaseString);
+ ctxt->node = save;
+ return result;
+}
+
static int
virNetworkDHCPHostDefParseXML(const char *networkName,
virNetworkIPDefPtr def,
xmlNodePtr node,
+ xmlXPathContextPtr ctxt,
virNetworkDHCPHostDefPtr host,
bool partialOkay)
{
char *mac = NULL, *name = NULL, *ip = NULL, *id = NULL;
virMacAddr addr;
virSocketAddr inaddr;
+ int64_t leasetime;
+ bool error;
int ret = -1;
mac = virXMLPropString(node, "mac");
@@ -1013,6 +1082,10 @@ virNetworkDHCPHostDefParseXML(const char
*networkName,
}
}
+ leasetime = virNetworkDHCPDefGetLeaseTime (node, ctxt,
"string(./@leasetime)", &error);
+ if (error)
+ goto cleanup;
+
host->mac = mac;
mac = NULL;
host->id = id;
@@ -1021,6 +1094,7 @@ virNetworkDHCPHostDefParseXML(const char *networkName,
name = NULL;
if (ip)
host->ip = inaddr;
+ host->leasetime = leasetime;
ret = 0;
cleanup:
@@ -1034,9 +1108,11 @@ virNetworkDHCPHostDefParseXML(const char
*networkName,
static int
virNetworkDHCPDefParseXML(const char *networkName,
xmlNodePtr node,
+ xmlXPathContextPtr ctxt,
virNetworkIPDefPtr def)
{
int ret = -1;
+ bool error;
xmlNodePtr cur;
virSocketAddrRange range;
virNetworkDHCPHostDef host;
@@ -1044,6 +1120,10 @@ virNetworkDHCPDefParseXML(const char *networkName,
memset(&range, 0, sizeof(range));
memset(&host, 0, sizeof(host));
+ def->leasetime = virNetworkDHCPDefGetLeaseTime (node, ctxt,
"string(./leasetime/text())", &error);
+ if (error)
+ goto cleanup;
+
cur = node->children;
while (cur != NULL) {
if (cur->type == XML_ELEMENT_NODE &&
@@ -1057,7 +1137,7 @@ virNetworkDHCPDefParseXML(const char *networkName,
} else if (cur->type == XML_ELEMENT_NODE &&
xmlStrEqual(cur->name, BAD_CAST "host")) {
- if (virNetworkDHCPHostDefParseXML(networkName, def, cur,
+ if (virNetworkDHCPHostDefParseXML(networkName, def, cur, ctxt,
&host, false) < 0)
goto cleanup;
if (VIR_APPEND_ELEMENT(def->hosts, def->nhosts, host) < 0)
@@ -1607,7 +1687,7 @@ virNetworkIPDefParseXML(const char *networkName,
while (cur != NULL) {
if (cur->type == XML_ELEMENT_NODE &&
xmlStrEqual(cur->name, BAD_CAST "dhcp")) {
- if (virNetworkDHCPDefParseXML(networkName, cur, def) < 0)
+ if (virNetworkDHCPDefParseXML(networkName, cur, ctxt, def) < 0)
goto cleanup;
} else if (cur->type == XML_ELEMENT_NODE &&
xmlStrEqual(cur->name, BAD_CAST "tftp")) {
@@ -3659,7 +3739,7 @@ virNetworkDefUpdateIPDHCPHost(virNetworkDefPtr def,
if (!ipdef)
goto cleanup;
- if (virNetworkDHCPHostDefParseXML(def->name, ipdef, ctxt->node,
+ if (virNetworkDHCPHostDefParseXML(def->name, ipdef, ctxt->node, ctxt,
&host, partialOkay) < 0)
goto cleanup;
diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h
index 3b227db..df687df 100644
--- a/src/conf/network_conf.h
+++ b/src/conf/network_conf.h
@@ -96,6 +96,7 @@ struct _virNetworkDHCPHostDef {
char *id;
char *name;
virSocketAddr ip;
+ int64_t leasetime;
};
typedef struct _virNetworkDNSTxtDef virNetworkDNSTxtDef;
@@ -170,7 +171,8 @@ struct _virNetworkIPDef {
char *tftproot;
char *bootfile;
virSocketAddr bootserver;
- };
+ int64_t leasetime;
+};
typedef struct _virNetworkForwardIfDef virNetworkForwardIfDef;
typedef virNetworkForwardIfDef *virNetworkForwardIfDefPtr;
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index b88e903..84fb62e 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1497,6 +1497,7 @@ dnsmasqCapsRefresh;
dnsmasqContextFree;
dnsmasqContextNew;
dnsmasqDelete;
+dnsmasqDhcpHostsToString;
dnsmasqReload;
dnsmasqSave;
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 7b99aca..dccf743 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -41,6 +41,8 @@
#include <sys/ioctl.h>
#include <net/if.h>
#include <dirent.h>
+#include <inttypes.h>
+#include <stdint.h>
#if HAVE_SYS_SYSCTL_H
# include <sys/sysctl.h>
#endif
@@ -859,30 +861,6 @@ networkKillDaemon(pid_t pid, const char *daemonName,
const char *networkName)
return ret;
}
-/* the following does not build a file, it builds a list
- * which is later saved into a file
- */
-
-static int
-networkBuildDnsmasqDhcpHostsList(dnsmasqContext *dctx,
- virNetworkIPDefPtr ipdef)
-{
- size_t i;
- bool ipv6 = false;
-
- if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET6))
- ipv6 = true;
- for (i = 0; i < ipdef->nhosts; i++) {
- virNetworkDHCPHostDefPtr host = &(ipdef->hosts[i]);
- if (VIR_SOCKET_ADDR_VALID(&host->ip))
- if (dnsmasqAddDhcpHost(dctx, host->mac, &host->ip,
- host->name, host->id, ipv6) < 0)
- return -1;
- }
-
- return 0;
-}
-
static int
networkBuildDnsmasqHostsList(dnsmasqContext *dctx,
virNetworkDNSDefPtr dnsdef)
@@ -903,11 +881,93 @@ networkBuildDnsmasqHostsList(dnsmasqContext *dctx,
return 0;
}
+/* translates the leasetime value into a dnsmasq configuration string for
dhcp-range/host */
+static char *
+networkDnsmasqConfLeaseValueToString (int64_t leasetime)
+{
+ char *result = NULL;
+ virBuffer leasebuf = VIR_BUFFER_INITIALIZER;
+
+ /* Leasetime parameter set on the XML */
+ /* Less than -1 means there was no value set */
+ if (leasetime < -1) {
+ virBufferAsprintf(&leasebuf, "%s", "");
+ }
+ /* -1 means no expiration */
+ else if (leasetime == -1)
+ virBufferAsprintf(&leasebuf, ",infinite");
+ /* Minimum expiry value is 120 */
+ /* TODO: Discuss if we should up as we do here or just forward
whatever value to dnsmasq */
+ else if (leasetime < 120)
+ virBufferAsprintf(&leasebuf, ",120");
+ /* DHCP value for lease time is a unsigned four octect integer */
+ else if (leasetime <= UINT32_MAX)
+ virBufferAsprintf(&leasebuf, ",%" PRId64, leasetime);
+ /* TODO: Discuss the use of "deprecated" for ipv6*/
+ /* TODO: Discuss what is the default value that we want as dnsmasq's
is 1 hour */
+ /* TODO: Discuss what to do if value exceeds maximum, use default
value for now */
+ else {
+ virBufferAsprintf(&leasebuf, "%s", "");
+ }
+
+ result = virBufferContentAndReset(&leasebuf);
+ virBufferFreeAndReset (&leasebuf);
+
+ return result;
+}
+
+/* the following does not build a file, it builds a list
+ * which is later saved into a file
+ */
+
+static int
+networkBuildDnsmasqDhcpHostsList(dnsmasqContext *dctx,
+ virNetworkIPDefPtr ipdef)
+{
+ int ret = -1;
+ size_t i;
+ bool ipv6 = false;
+ char *leasetime = networkDnsmasqConfLeaseValueTo
String(ipdef->leasetime);
+
+ if (!leasetime)
+ goto cleanup;
+
+ if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET6))
+ ipv6 = true;
+ for (i = 0; i < ipdef->nhosts; i++) {
+ virNetworkDHCPHostDefPtr host = &(ipdef->hosts[i]);
+ if (VIR_SOCKET_ADDR_VALID(&host->ip)) {
+ /* If the host has its own leasetime we get its specific
string */
+ if (host->leasetime > -2) {
+ char *hostlease = networkDnsmasqConfLeaseValueTo
String(host->leasetime);
+ if (!hostlease)
+ goto cleanup;
+ if (dnsmasqAddDhcpHost(dctx, host->mac, &host->ip,
+ host->name, host->id, hostlease,
ipv6) < 0) {
+ VIR_FREE(hostlease);
+ goto cleanup;
+ }
+ VIR_FREE(hostlease);
+ } else {
+ /* Otherwise we use the leasetime from dhcp */
+ if (dnsmasqAddDhcpHost(dctx, host->mac, &host->ip,
+ host->name, host->id, leasetime,
ipv6) < 0)
+ goto cleanup;
+ }
+ }
+ }
+
+ ret = 0;
+cleanup:
+ VIR_FREE(leasetime);
+ return ret;
+}
int
networkDnsmasqConfContents(virNetworkObjPtr network,
const char *pidfile,
char **configstr,
+ char **hostsfilestr,
dnsmasqContext *dctx,
dnsmasqCapsPtr caps ATTRIBUTE_UNUSED)
{
@@ -1213,6 +1273,7 @@ networkDnsmasqConfContents(virNetworkObjPtr network,
}
for (r = 0; r < ipdef->nranges; r++) {
int thisRange;
+ char *leasestr;
if (!(saddr = virSocketAddrFormat(&ipdef->ranges[r].start)) ||
!(eaddr = virSocketAddrFormat(&ipdef->ranges[r].end)))
@@ -1220,12 +1281,22 @@ networkDnsmasqConfContents(virNetworkObjPtr network,
virBufferAsprintf(&configbuf, "dhcp-range=%s,%s",
saddr, eaddr);
- if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET6))
+
+ /* Add ipv6 prefix length parameter if needed */
+ if (ipdef == ipv6def)
virBufferAsprintf(&configbuf, ",%d", prefix);
+
+ leasestr = networkDnsmasqConfLeaseValueToString
(ipdef->leasetime);
+ if (!leasestr)
+ goto cleanup;
+ virBufferAsprintf(&configbuf, "%s", leasestr);
+
+ /* Add the newline */
virBufferAddLit(&configbuf, "\n");
VIR_FREE(saddr);
VIR_FREE(eaddr);
+ VIR_FREE(leasestr);
thisRange = virSocketAddrGetRange(&ipdef->ranges[r].start,
&ipdef->ranges[r].end,
&ipdef->address,
@@ -1256,6 +1327,15 @@ networkDnsmasqConfContents(virNetworkObjPtr network,
if (networkBuildDnsmasqDhcpHostsList(dctx, ipdef) < 0)
goto cleanup;
+ /* Return the contents of the hostsfile if requested */
+ if (hostsfilestr) {
+ *hostsfilestr = dnsmasqDhcpHostsToString
(dctx->hostsfile->hosts,
+
dctx->hostsfile->nhosts);
+
+ if (!hostsfilestr)
+ goto cleanup;
+ }
+
/* Note: the following is IPv4 only */
if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET)) {
if (ipdef->nranges || ipdef->nhosts)
@@ -1355,7 +1435,7 @@
networkBuildDhcpDaemonCommandLine(virNetworkDriverStatePtr
driver,
network->dnsmasqPid = -1;
- if (networkDnsmasqConfContents(network, pidfile, &configstr,
+ if (networkDnsmasqConfContents(network, pidfile, &configstr, NULL,
dctx, dnsmasq_caps) < 0)
goto cleanup;
if (!configstr)
diff --git a/src/network/bridge_driver.h b/src/network/bridge_driver.h
index ff7f921..c653c50 100644
--- a/src/network/bridge_driver.h
+++ b/src/network/bridge_driver.h
@@ -53,6 +53,7 @@ int networkGetActualType(virDomainNetDefPtr iface)
int networkDnsmasqConfContents(virNetworkObjPtr network,
const char *pidfile,
char **configstr,
+ char **hostsfilestr,
dnsmasqContext *dctx,
dnsmasqCapsPtr caps);
diff --git a/src/util/virdnsmasq.c b/src/util/virdnsmasq.c
index 1b78c1f..94c9a3b 100644
--- a/src/util/virdnsmasq.c
+++ b/src/util/virdnsmasq.c
@@ -308,52 +308,47 @@ hostsfileAdd(dnsmasqHostsfile *hostsfile,
virSocketAddr *ip,
const char *name,
const char *id,
+ const char *leasetime,
bool ipv6)
{
+ int ret = -1;
char *ipstr = NULL;
+ virBuffer hostbuf = VIR_BUFFER_INITIALIZER;
+
if (VIR_REALLOC_N(hostsfile->hosts, hostsfile->nhosts + 1) < 0)
goto error;
if (!(ipstr = virSocketAddrFormat(ip)))
- return -1;
+ goto error;
/* the first test determines if it is a dhcpv6 host */
if (ipv6) {
- if (name && id) {
- if (virAsprintf(&hostsfile->hosts[hostsfile->nhosts].host,
- "id:%s,%s,[%s]", id, name, ipstr) < 0)
- goto error;
- } else if (name && !id) {
- if (virAsprintf(&hostsfile->hosts[hostsfile->nhosts].host,
- "%s,[%s]", name, ipstr) < 0)
- goto error;
- } else if (!name && id) {
- if (virAsprintf(&hostsfile->hosts[hostsfile->nhosts].host,
- "id:%s,[%s]", id, ipstr) < 0)
- goto error;
- }
+ if (name && id)
+ virBufferAsprintf(&hostbuf, "id:%s,%s,[%s]", id, name, ipstr);
+ else if (name && !id)
+ virBufferAsprintf(&hostbuf, "%s,[%s]", name, ipstr);
+ else if (!name && id)
+ virBufferAsprintf(&hostbuf, "id:%s,[%s]", id, ipstr);
} else if (name && mac) {
- if (virAsprintf(&hostsfile->hosts[hostsfile->nhosts].host,
"%s,%s,%s",
- mac, ipstr, name) < 0)
- goto error;
+ virBufferAsprintf(&hostbuf, "%s,%s,%s", mac, ipstr, name);
} else if (name && !mac) {
- if (virAsprintf(&hostsfile->hosts[hostsfile->nhosts].host, "%s,%s",
- name, ipstr) < 0)
- goto error;
+ virBufferAsprintf(&hostbuf, "%s,%s", name, ipstr);
} else {
- if (virAsprintf(&hostsfile->hosts[hostsfile->nhosts].host, "%s,%s",
- mac, ipstr) < 0)
- goto error;
+ virBufferAsprintf(&hostbuf, "%s,%s", mac, ipstr);
}
- VIR_FREE(ipstr);
- hostsfile->nhosts++;
+ /* The leasetime string already includes comma if there's any value at
all */
+ virBufferAsprintf(&hostbuf, "%s", leasetime);
- return 0;
+ if (!(hostsfile->hosts[hostsfile->nhosts].host =
virBufferContentAndReset (&hostbuf)))
+ goto error;
+ hostsfile->nhosts++;
+ ret = 0;
error:
+ virBufferFreeAndReset(&hostbuf);
VIR_FREE(ipstr);
- return -1;
+ return ret;
}
static dnsmasqHostsfile *
@@ -391,10 +386,9 @@ hostsfileWrite(const char *path,
dnsmasqDhcpHost *hosts,
unsigned int nhosts)
{
- char *tmp;
+ char *tmp, *content = NULL;
FILE *f;
bool istmp = true;
- size_t i;
int rc = 0;
/* even if there are 0 hosts, create a 0 length file, to allow
@@ -412,17 +406,21 @@ hostsfileWrite(const char *path,
}
}
- for (i = 0; i < nhosts; i++) {
- if (fputs(hosts[i].host, f) == EOF || fputc('\n', f) == EOF) {
- rc = -errno;
- VIR_FORCE_FCLOSE(f);
+ if (!(content = dnsmasqDhcpHostsToString(hosts, nhosts))) {
+ rc = -ENOMEM;
+ goto cleanup;
+ }
- if (istmp)
- unlink(tmp);
+ if (fputs(content, f) == EOF) {
+ rc = -errno;
+ VIR_FORCE_FCLOSE(f);
+
+ if (istmp)
+ unlink(tmp);
+
+ goto cleanup;
+ }
- goto cleanup;
- }
- }
if (VIR_FCLOSE(f) == EOF) {
rc = -errno;
@@ -436,6 +434,7 @@ hostsfileWrite(const char *path,
}
cleanup:
+ VIR_FREE(content);
VIR_FREE(tmp);
return rc;
@@ -524,9 +523,10 @@ dnsmasqAddDhcpHost(dnsmasqContext *ctx,
virSocketAddr *ip,
const char *name,
const char *id,
+ const char *leasetime,
bool ipv6)
{
- return hostsfileAdd(ctx->hostsfile, mac, ip, name, id, ipv6);
+ return hostsfileAdd(ctx->hostsfile, mac, ip, name, id, leasetime,
ipv6);
}
/*
@@ -892,3 +892,31 @@ dnsmasqCapsGet(dnsmasqCapsPtr caps, dnsmasqCapsFlags
flag)
return caps && virBitmapIsBitSet(caps->flags, flag);
}
+
+/** dnsmasqDhcpHostsToString:
+ *
+ * Turns a vector of dnsmasqDhcpHost into the string that is ought to be
+ * stored in the hostsfile, this functionality is split to make
hostsfiles
+ * testable. Returs NULL if nhosts is 0.
+ */
+char *
+dnsmasqDhcpHostsToString (dnsmasqDhcpHost *hosts,
+ unsigned int nhosts)
+{
+ int i;
+ char *result = NULL;
+ virBuffer hostsfilebuf = VIR_BUFFER_INITIALIZER;
+
+ if (nhosts == 0)
+ goto cleanup;
+
+ for (i = 0; i < nhosts; i++) {
+ virBufferAsprintf(&hostsfilebuf, "%s\n", hosts[i].host);
+ }
+
+ result = virBufferContentAndReset(&hostsfilebuf);
+
+cleanup:
+ virBufferFreeAndReset(&hostsfilebuf);
+ return result;
+}
diff --git a/src/util/virdnsmasq.h b/src/util/virdnsmasq.h
index f47bea3..1795bc8 100644
--- a/src/util/virdnsmasq.h
+++ b/src/util/virdnsmasq.h
@@ -88,6 +88,7 @@ int dnsmasqAddDhcpHost(dnsmasqContext *ctx,
virSocketAddr *ip,
const char *name,
const char *id,
+ const char *leastime,
bool ipv6);
int dnsmasqAddHost(dnsmasqContext *ctx,
virSocketAddr *ip,
@@ -105,6 +106,7 @@ int dnsmasqCapsRefresh(dnsmasqCapsPtr *caps, const char
*binaryPath);
bool dnsmasqCapsGet(dnsmasqCapsPtr caps, dnsmasqCapsFlags flag);
const char *dnsmasqCapsGetBinaryPath(dnsmasqCapsPtr caps);
unsigned long dnsmasqCapsGetVersion(dnsmasqCapsPtr caps);
+char *dnsmasqDhcpHostsToString(dnsmasqDhcpHost *hosts, unsigned int
nhosts);
# define DNSMASQ_DHCPv6_MAJOR_REQD 2
# define DNSMASQ_DHCPv6_MINOR_REQD 64
diff --git a/tests/networkxml2confdata/dhcp6-nat-network.hostsfile
b/tests/networkxml2confdata/dhcp6-nat-network.hostsfile
new file mode 100644
index 0000000..de659b9
--- /dev/null
+++ b/tests/networkxml2confdata/dhcp6-nat-network.hostsfile
@@ -0,0 +1,7 @@
+00:16:3e:77:e2:ed,192.168.122.10,a.example.com
+00:16:3e:3e:a9:1a,192.168.122.11,b.example.com
+id:0:4:7e:7d:f0:7d:a8:bc:c5:d2:13:32:11:ed:16:ea:84:63,[
2001:db8:ac10:fd01::1:20]
+paul,[2001:db8:ac10:fd01::1:21]
+id:0:3:0:1:0:16:3e:11:22:33,peter.xyz,[2001:db8:ac10:fd01::1:22]
+id:0:3:0:1:0:16:3e:44:55:33,[2001:db8:ac10:fd01::1:23]
+id:0:1:0:1:18:aa:62:fe:0:16:3e:44:55:66,badbob,[2001:db8:ac10:fd01::1:24]
diff --git a/tests/networkxml2confdata/dhcp6-network.hostsfile
b/tests/networkxml2confdata/dhcp6-network.hostsfile
new file mode 100644
index 0000000..9dfb172
--- /dev/null
+++ b/tests/networkxml2confdata/dhcp6-network.hostsfile
@@ -0,0 +1,5 @@
+id:0:4:7e:7d:f0:7d:a8:bc:c5:d2:13:32:11:ed:16:ea:84:63,[
2001:db8:ac10:fd01::1:20]
+paul,[2001:db8:ac10:fd01::1:21]
+id:0:3:0:1:0:16:3e:11:22:33,peter.xyz,[2001:db8:ac10:fd01::1:22]
+id:0:3:0:1:0:16:3e:44:55:33,[2001:db8:ac10:fd01::1:23]
+id:0:1:0:1:18:aa:62:fe:0:16:3e:44:55:66,badbob,[2001:db8:ac10:fd01::1:24]
diff --git a/tests/networkxml2confdata/dhcp6host-routed-network.hostsfile
b/tests/networkxml2confdata/dhcp6host-routed-network.hostsfile
new file mode 100644
index 0000000..de659b9
--- /dev/null
+++ b/tests/networkxml2confdata/dhcp6host-routed-network.hostsfile
@@ -0,0 +1,7 @@
+00:16:3e:77:e2:ed,192.168.122.10,a.example.com
+00:16:3e:3e:a9:1a,192.168.122.11,b.example.com
+id:0:4:7e:7d:f0:7d:a8:bc:c5:d2:13:32:11:ed:16:ea:84:63,[
2001:db8:ac10:fd01::1:20]
+paul,[2001:db8:ac10:fd01::1:21]
+id:0:3:0:1:0:16:3e:11:22:33,peter.xyz,[2001:db8:ac10:fd01::1:22]
+id:0:3:0:1:0:16:3e:44:55:33,[2001:db8:ac10:fd01::1:23]
+id:0:1:0:1:18:aa:62:fe:0:16:3e:44:55:66,badbob,[2001:db8:ac10:fd01::1:24]
diff --git a/tests/networkxml2confdata/leasetime-days.conf
b/tests/networkxml2confdata/leasetime-days.conf
new file mode 100644
index 0000000..9501e2f
--- /dev/null
+++ b/tests/networkxml2confdata/leasetime-days.conf
@@ -0,0 +1,17 @@
+##WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE
+##OVERWRITTEN AND LOST. Changes to this configuration should be made
using:
+## virsh net-edit default
+## or other application using the libvirt API.
+##
+## dnsmasq conf file created by libvirt
+strict-order
+except-interface=lo
+bind-dynamic
+interface=virbr0
+dhcp-range=192.168.122.2,192.168.122.254,86400
+dhcp-no-override
+dhcp-range=2001:db8:ac10:fd01::1:10,2001:db8:ac10:fd01::1:ff,64,86400
+dhcp-lease-max=493
+dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile
+addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts
+enable-ra
diff --git a/tests/networkxml2confdata/leasetime-days.xml
b/tests/networkxml2confdata/leasetime-days.xml
new file mode 100644
index 0000000..1a507d5
--- /dev/null
+++ b/tests/networkxml2confdata/leasetime-days.xml
@@ -0,0 +1,18 @@
+<network>
+ <name>default</name>
+ <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid>
+ <forward dev='eth1' mode='nat'/>
+ <bridge name='virbr0' stp='on' delay='0'/>
+ <ip address='192.168.122.1' netmask='255.255.255.0'>
+ <dhcp>
+ <leasetime>1d</leasetime>
+ <range start='192.168.122.2' end='192.168.122.254'/>
+ </dhcp>
+ </ip>
+ <ip family='ipv6' address='2001:db8:ac10:fd01::1' prefix='64'>
+ <dhcp>
+ <leasetime>1d</leasetime>
+ <range start='2001:db8:ac10:fd01::1:10'
end='2001:db8:ac10:fd01::1:ff'/>
+ </dhcp>
+ </ip>
+</network>
diff --git a/tests/networkxml2confdata/leasetime-host.conf
b/tests/networkxml2confdata/leasetime-host.conf
new file mode 100644
index 0000000..7bd2054
--- /dev/null
+++ b/tests/networkxml2confdata/leasetime-host.conf
@@ -0,0 +1,16 @@
+##WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE
+##OVERWRITTEN AND LOST. Changes to this configuration should be made
using:
+## virsh net-edit default
+## or other application using the libvirt API.
+##
+## dnsmasq conf file created by libvirt
+strict-order
+except-interface=lo
+bind-dynamic
+interface=virbr0
+srv-host=_name._tcp
+dhcp-range=192.168.122.2,192.168.122.254
+dhcp-no-override
+dhcp-lease-max=253
+dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile
+addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts
diff --git a/tests/networkxml2confdata/leasetime-host.hostsfile
b/tests/networkxml2confdata/leasetime-host.hostsfile
new file mode 100644
index 0000000..fd20ca2
--- /dev/null
+++ b/tests/networkxml2confdata/leasetime-host.hostsfile
@@ -0,0 +1,6 @@
+00:16:3e:3e:a9:01,192.168.122.11,a.example.com,3600
+00:16:3e:3e:a9:02,192.168.122.12,b.example.com,3600
+00:16:3e:3e:a9:03,192.168.122.13,c.example.com,3600
+00:16:3e:3e:a9:04,192.168.122.14,d.example.com,86400
+00:16:3e:3e:a9:05,192.168.122.15,e.example.com,3600
+00:16:3e:3e:a9:06,192.168.122.16,f.example.com,infinite
diff --git a/tests/networkxml2confdata/leasetime-host.xml
b/tests/networkxml2confdata/leasetime-host.xml
new file mode 100644
index 0000000..276d3e5
--- /dev/null
+++ b/tests/networkxml2confdata/leasetime-host.xml
@@ -0,0 +1,22 @@
+<network>
+ <name>default</name>
+ <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid>
+ <forward dev='eth1' mode='nat'>
+ <interface dev='eth1'/>
+ </forward>
+ <bridge name='virbr0' stp='on' delay='0'/>
+ <dns>
+ <srv service='name' protocol='tcp'/>
+ </dns>
+ <ip address='192.168.122.1' netmask='255.255.255.0'>
+ <dhcp>
+ <range start='192.168.122.2' end='192.168.122.254'/>
+ <host mac='00:16:3e:3e:a9:1a' name='a.example.com'
ip='192.168.122.11' leasetime="3600s"/>
+ <host mac='00:16:3e:3e:a9:1b' name='b.example.com'
ip='192.168.122.12' leasetime="60m"/>
+ <host mac='00:16:3e:3e:a9:1c' name='c.example.com'
ip='192.168.122.13' leasetime="1h"/>
+ <host mac='00:16:3e:3e:a9:1d' name='d.example.com'
ip='192.168.122.14' leasetime="1d"/>
+ <host mac='00:16:3e:3e:a9:1e' name='e.example.com'
ip='192.168.122.15' leasetime="3600"/>
+ <host mac='00:16:3e:3e:a9:1f' name='f.example.com'
ip='192.168.122.16' leasetime="-1"/>
+ </dhcp>
+ </ip>
+</network>
diff --git a/tests/networkxml2confdata/leasetime-hours.conf
b/tests/networkxml2confdata/leasetime-hours.conf
new file mode 100644
index 0000000..021a769
--- /dev/null
+++ b/tests/networkxml2confdata/leasetime-hours.conf
@@ -0,0 +1,17 @@
+##WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE
+##OVERWRITTEN AND LOST. Changes to this configuration should be made
using:
+## virsh net-edit default
+## or other application using the libvirt API.
+##
+## dnsmasq conf file created by libvirt
+strict-order
+except-interface=lo
+bind-dynamic
+interface=virbr0
+dhcp-range=192.168.122.2,192.168.122.254,3600
+dhcp-no-override
+dhcp-range=2001:db8:ac10:fd01::1:10,2001:db8:ac10:fd01::1:ff,64,3600
+dhcp-lease-max=493
+dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile
+addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts
+enable-ra
diff --git a/tests/networkxml2confdata/leasetime-hours.xml
b/tests/networkxml2confdata/leasetime-hours.xml
new file mode 100644
index 0000000..36dc600
--- /dev/null
+++ b/tests/networkxml2confdata/leasetime-hours.xml
@@ -0,0 +1,18 @@
+<network>
+ <name>default</name>
+ <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid>
+ <forward dev='eth1' mode='nat'/>
+ <bridge name='virbr0' stp='on' delay='0'/>
+ <ip address='192.168.122.1' netmask='255.255.255.0'>
+ <dhcp>
+ <leasetime>1h</leasetime>
+ <range start='192.168.122.2' end='192.168.122.254'/>
+ </dhcp>
+ </ip>
+ <ip family='ipv6' address='2001:db8:ac10:fd01::1' prefix='64'>
+ <dhcp>
+ <leasetime>1h</leasetime>
+ <range start='2001:db8:ac10:fd01::1:10'
end='2001:db8:ac10:fd01::1:ff'/>
+ </dhcp>
+ </ip>
+</network>
diff --git a/tests/networkxml2confdata/leasetime-infinite.conf
b/tests/networkxml2confdata/leasetime-infinite.conf
new file mode 100644
index 0000000..cc21135
--- /dev/null
+++ b/tests/networkxml2confdata/leasetime-infinite.conf
@@ -0,0 +1,17 @@
+##WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE
+##OVERWRITTEN AND LOST. Changes to this configuration should be made
using:
+## virsh net-edit default
+## or other application using the libvirt API.
+##
+## dnsmasq conf file created by libvirt
+strict-order
+except-interface=lo
+bind-dynamic
+interface=virbr0
+dhcp-range=192.168.122.2,192.168.122.254,infinite
+dhcp-no-override
+dhcp-range=2001:db8:ac10:fd01::1:10,2001:db8:ac10:fd01::1:ff,64,infinite
+dhcp-lease-max=493
+dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile
+addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts
+enable-ra
diff --git a/tests/networkxml2confdata/leasetime-infinite.xml
b/tests/networkxml2confdata/leasetime-infinite.xml
new file mode 100644
index 0000000..bc8740e
--- /dev/null
+++ b/tests/networkxml2confdata/leasetime-infinite.xml
@@ -0,0 +1,18 @@
+<network>
+ <name>default</name>
+ <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid>
+ <forward dev='eth1' mode='nat'/>
+ <bridge name='virbr0' stp='on' delay='0'/>
+ <ip address='192.168.122.1' netmask='255.255.255.0'>
+ <dhcp>
+ <leasetime>-1</leasetime>
+ <range start='192.168.122.2' end='192.168.122.254'/>
+ </dhcp>
+ </ip>
+ <ip family='ipv6' address='2001:db8:ac10:fd01::1' prefix='64'>
+ <dhcp>
+ <leasetime>-1</leasetime>
+ <range start='2001:db8:ac10:fd01::1:10'
end='2001:db8:ac10:fd01::1:ff'/>
+ </dhcp>
+ </ip>
+</network>
diff --git a/tests/networkxml2confdata/leasetime-minutes.conf
b/tests/networkxml2confdata/leasetime-minutes.conf
new file mode 100644
index 0000000..db68895
--- /dev/null
+++ b/tests/networkxml2confdata/leasetime-minutes.conf
@@ -0,0 +1,17 @@
+##WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE
+##OVERWRITTEN AND LOST. Changes to this configuration should be made
using:
+## virsh net-edit default
+## or other application using the libvirt API.
+##
+## dnsmasq conf file created by libvirt
+strict-order
+except-interface=lo
+bind-dynamic
+interface=virbr0
+dhcp-range=192.168.122.2,192.168.122.254,300
+dhcp-no-override
+dhcp-range=2001:db8:ac10:fd01::1:10,2001:db8:ac10:fd01::1:ff,64,300
+dhcp-lease-max=493
+dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile
+addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts
+enable-ra
diff --git a/tests/networkxml2confdata/leasetime-minutes.xml
b/tests/networkxml2confdata/leasetime-minutes.xml
new file mode 100644
index 0000000..7c1df25
--- /dev/null
+++ b/tests/networkxml2confdata/leasetime-minutes.xml
@@ -0,0 +1,18 @@
+<network>
+ <name>default</name>
+ <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid>
+ <forward dev='eth1' mode='nat'/>
+ <bridge name='virbr0' stp='on' delay='0'/>
+ <ip address='192.168.122.1' netmask='255.255.255.0'>
+ <dhcp>
+ <leasetime>5m</leasetime>
+ <range start='192.168.122.2' end='192.168.122.254'/>
+ </dhcp>
+ </ip>
+ <ip family='ipv6' address='2001:db8:ac10:fd01::1' prefix='64'>
+ <dhcp>
+ <leasetime>5m</leasetime>
+ <range start='2001:db8:ac10:fd01::1:10'
end='2001:db8:ac10:fd01::1:ff'/>
+ </dhcp>
+ </ip>
+</network>
diff --git a/tests/networkxml2confdata/leasetime-seconds.conf
b/tests/networkxml2confdata/leasetime-seconds.conf
new file mode 100644
index 0000000..635896b
--- /dev/null
+++ b/tests/networkxml2confdata/leasetime-seconds.conf
@@ -0,0 +1,17 @@
+##WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE
+##OVERWRITTEN AND LOST. Changes to this configuration should be made
using:
+## virsh net-edit default
+## or other application using the libvirt API.
+##
+## dnsmasq conf file created by libvirt
+strict-order
+except-interface=lo
+bind-dynamic
+interface=virbr0
+dhcp-range=192.168.122.2,192.168.122.254,125
+dhcp-no-override
+dhcp-range=2001:db8:ac10:fd01::1:10,2001:db8:ac10:fd01::1:ff,64,125
+dhcp-lease-max=493
+dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile
+addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts
+enable-ra
diff --git a/tests/networkxml2confdata/leasetime-seconds.xml
b/tests/networkxml2confdata/leasetime-seconds.xml
new file mode 100644
index 0000000..dcb3f91
--- /dev/null
+++ b/tests/networkxml2confdata/leasetime-seconds.xml
@@ -0,0 +1,18 @@
+<network>
+ <name>default</name>
+ <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid>
+ <forward dev='eth1' mode='nat'/>
+ <bridge name='virbr0' stp='on' delay='0'/>
+ <ip address='192.168.122.1' netmask='255.255.255.0'>
+ <dhcp>
+ <leasetime>125s</leasetime>
+ <range start='192.168.122.2' end='192.168.122.254'/>
+ </dhcp>
+ </ip>
+ <ip family='ipv6' address='2001:db8:ac10:fd01::1' prefix='64'>
+ <dhcp>
+ <leasetime>125s</leasetime>
+ <range start='2001:db8:ac10:fd01::1:10'
end='2001:db8:ac10:fd01::1:ff'/>
+ </dhcp>
+ </ip>
+</network>
diff --git a/tests/networkxml2confdata/leasetime.conf
b/tests/networkxml2confdata/leasetime.conf
new file mode 100644
index 0000000..72a2f69
--- /dev/null
+++ b/tests/networkxml2confdata/leasetime.conf
@@ -0,0 +1,17 @@
+##WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE
+##OVERWRITTEN AND LOST. Changes to this configuration should be made
using:
+## virsh net-edit default
+## or other application using the libvirt API.
+##
+## dnsmasq conf file created by libvirt
+strict-order
+except-interface=lo
+bind-dynamic
+interface=virbr0
+dhcp-range=192.168.122.2,192.168.122.254,122
+dhcp-no-override
+dhcp-range=2001:db8:ac10:fd01::1:10,2001:db8:ac10:fd01::1:ff,64,121
+dhcp-lease-max=493
+dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile
+addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts
+enable-ra
diff --git a/tests/networkxml2confdata/leasetime.xml
b/tests/networkxml2confdata/leasetime.xml
new file mode 100644
index 0000000..fdbb15f
--- /dev/null
+++ b/tests/networkxml2confdata/leasetime.xml
@@ -0,0 +1,18 @@
+<network>
+ <name>default</name>
+ <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid>
+ <forward dev='eth1' mode='nat'/>
+ <bridge name='virbr0' stp='on' delay='0'/>
+ <ip address='192.168.122.1' netmask='255.255.255.0'>
+ <dhcp>
+ <leasetime>122</leasetime>
+ <range start='192.168.122.2' end='192.168.122.254'/>
+ </dhcp>
+ </ip>
+ <ip family='ipv6' address='2001:db8:ac10:fd01::1' prefix='64'>
+ <dhcp>
+ <leasetime>121</leasetime>
+ <range start='2001:db8:ac10:fd01::1:10'
end='2001:db8:ac10:fd01::1:ff'/>
+ </dhcp>
+ </ip>
+</network>
diff --git a/tests/networkxml2confdata/nat-network-dns-srv-record-minimal.hostsfile
b/tests/networkxml2confdata/nat-network-dns-srv-record-minimal.hostsfile
new file mode 100644
index 0000000..deb3f00
--- /dev/null
+++ b/tests/networkxml2confdata/nat-network-dns-srv-record-minimal.hostsfile
@@ -0,0 +1,2 @@
+00:16:3e:77:e2:ed,192.168.122.10,a.example.com
+00:16:3e:3e:a9:1a,192.168.122.11,b.example.com
diff --git a/tests/networkxml2confdata/nat-network-dns-srv-record.hostsfile
b/tests/networkxml2confdata/nat-network-dns-srv-record.hostsfile
new file mode 100644
index 0000000..deb3f00
--- /dev/null
+++ b/tests/networkxml2confdata/nat-network-dns-srv-record.hostsfile
@@ -0,0 +1,2 @@
+00:16:3e:77:e2:ed,192.168.122.10,a.example.com
+00:16:3e:3e:a9:1a,192.168.122.11,b.example.com
diff --git a/tests/networkxml2confdata/nat-network-dns-txt-record.hostsfile
b/tests/networkxml2confdata/nat-network-dns-txt-record.hostsfile
new file mode 100644
index 0000000..deb3f00
--- /dev/null
+++ b/tests/networkxml2confdata/nat-network-dns-txt-record.hostsfile
@@ -0,0 +1,2 @@
+00:16:3e:77:e2:ed,192.168.122.10,a.example.com
+00:16:3e:3e:a9:1a,192.168.122.11,b.example.com
diff --git a/tests/networkxml2confdata/nat-network-name-with-quotes.hostsfile
b/tests/networkxml2confdata/nat-network-name-with-quotes.hostsfile
new file mode 100644
index 0000000..deb3f00
--- /dev/null
+++ b/tests/networkxml2confdata/nat-network-name-with-quotes.hostsfile
@@ -0,0 +1,2 @@
+00:16:3e:77:e2:ed,192.168.122.10,a.example.com
+00:16:3e:3e:a9:1a,192.168.122.11,b.example.com
diff --git a/tests/networkxml2confdata/nat-network.hostsfile
b/tests/networkxml2confdata/nat-network.hostsfile
new file mode 100644
index 0000000..deb3f00
--- /dev/null
+++ b/tests/networkxml2confdata/nat-network.hostsfile
@@ -0,0 +1,2 @@
+00:16:3e:77:e2:ed,192.168.122.10,a.example.com
+00:16:3e:3e:a9:1a,192.168.122.11,b.example.com
diff --git a/tests/networkxml2conftest.c b/tests/networkxml2conftest.c
index 65a0e32..8e1f8be 100644
--- a/tests/networkxml2conftest.c
+++ b/tests/networkxml2conftest.c
@@ -19,9 +19,13 @@
#define VIR_FROM_THIS VIR_FROM_NONE
static int
-testCompareXMLToConfFiles(const char *inxml, const char *outconf,
dnsmasqCapsPtr caps)
+testCompareXMLToConfFiles(const char *inxml,
+ const char *outconf,
+ const char *outhostsfile,
+ dnsmasqCapsPtr caps)
{
- char *actual = NULL;
+ char *actualconf = NULL;
+ char *actualhosts = NULL;
int ret = -1;
virNetworkDefPtr dev = NULL;
virNetworkObjPtr obj = NULL;
@@ -41,17 +45,30 @@ testCompareXMLToConfFiles(const char *inxml, const char
*outconf, dnsmasqCapsPtr
if (dctx == NULL)
goto fail;
- if (networkDnsmasqConfContents(obj, pidfile, &actual,
+ if (networkDnsmasqConfContents(obj, pidfile, &actualconf, &actualhosts,
dctx, caps) < 0)
goto fail;
- if (virTestCompareToFile(actual, outconf) < 0)
+ if (virTestCompareToFile(actualconf, outconf) < 0)
goto fail;
+ if (virFileExists(outhostsfile)) {
+ if (!actualhosts) {
+ fprintf(stderr, "%s: hostsfile exists but the configuration
did not specify any host", outhostsfile);
+ goto fail;
+ } else if (virTestCompareToFile(actualhosts, outhostsfile) < 0) {
+ goto fail;
+ }
+ } else if (actualhosts) {
+ fprintf(stderr, "%s: file does not exist but actual data was
expected", outhostsfile);
+ goto fail;
+ }
+
ret = 0;
fail:
- VIR_FREE(actual);
+ VIR_FREE(actualconf);
+ VIR_FREE(actualhosts);
VIR_FREE(pidfile);
virCommandFree(cmd);
virObjectUnref(obj);
@@ -70,20 +87,24 @@ testCompareXMLToConfHelper(const void *data)
int result = -1;
const testInfo *info = data;
char *inxml = NULL;
- char *outxml = NULL;
+ char *outconf = NULL;
+ char *outhostsfile = NULL;
if (virAsprintf(&inxml, "%s/networkxml2confdata/%s.xml",
abs_srcdir, info->name) < 0 ||
- virAsprintf(&outxml, "%s/networkxml2confdata/%s.conf",
+ virAsprintf(&outconf, "%s/networkxml2confdata/%s.conf",
+ abs_srcdir, info->name) < 0 ||
+ virAsprintf(&outhostsfile, "%s/networkxml2confdata/%s.hostsfile",
abs_srcdir, info->name) < 0) {
goto cleanup;
}
- result = testCompareXMLToConfFiles(inxml, outxml, info->caps);
+ result = testCompareXMLToConfFiles(inxml, outconf, outhostsfile,
info->caps);
cleanup:
VIR_FREE(inxml);
- VIR_FREE(outxml);
+ VIR_FREE(outconf);
+ VIR_FREE(outhostsfile);
return result;
}
@@ -129,6 +150,14 @@ mymain(void)
DO_TEST("dhcp6-network", dhcpv6);
DO_TEST("dhcp6-nat-network", dhcpv6);
DO_TEST("dhcp6host-routed-network", dhcpv6);
+ DO_TEST("leasetime", dhcpv6);
+ DO_TEST("leasetime-seconds", dhcpv6);
+ DO_TEST("leasetime-hours", dhcpv6);
+ DO_TEST("leasetime-minutes", dhcpv6);
+ DO_TEST("leasetime-hours", dhcpv6);
+ DO_TEST("leasetime-days", dhcpv6);
+ DO_TEST("leasetime-infinite", dhcpv6);
+ DO_TEST("leasetime-host", dhcpv6);
virObjectUnref(dhcpv6);
virObjectUnref(full);
--
2.9.3
--
Alberto Ruiz
Associate Engineering Manager - Desktop Management Tools
Red Hat
7 years, 6 months
[libvirt] libvirt-python bug: custom event loop impl calls ff callback from *Remove(Handle|Timeout)Func
by Wojtek Porczyk
Hello libvirt-list,
As of current libvirt-python.git, according to libvirt-override.c, if
implementing custom event loop in Python, ff callback is called from
libvirt_virEventRemoveHandleFunc, which is a C glue between
virEventRegisterImpl and actual removeHandle function written in Python:
> result = PyEval_CallObject(removeHandleObj, pyobj_args);
> if (!result) {
> PyErr_Print();
> PyErr_Clear();
> } else if (!PyTuple_Check(result) || PyTuple_Size(result) != 3) {
> DEBUG("%s: %s must return opaque obj registered with %s"
> "to avoid leaking libvirt memory\n",
> __FUNCTION__, NAME(removeHandle), NAME(addHandle));
> } else {
> opaque = PyTuple_GetItem(result, 1);
> ff = PyTuple_GetItem(result, 2);
> cff = PyvirFreeCallback_Get(ff);
> if (cff)
> (*cff)(PyvirVoidPtr_Get(opaque));
> retval = 0;
> }
This is exactly what one shoud not be doing according to documentation [1]:
> If the opaque user data requires free'ing when the handle is unregistered,
> then a 2nd callback can be supplied for this purpose. This callback needs to
> be invoked from a clean stack. If 'ff' callbacks are invoked directly from the
> virEventRemoveHandleFunc they will likely deadlock in libvirt.
[1] https://libvirt.org/html/libvirt-libvirt-event.html#virEventAddHandleFunc
This is true, the deadlock occurs. When the "result" tuple is mangled to have
None as third item ("ff"), then cff = PyvirFreeCallback_Get(ff) is NULL and
the deadlock does not happen.
That's also why script examples/event-test.py does not deadlock, because it
does not return anything (that is, returns None) from Python, so the second if
block happens and the ff callback, if any, is not executed (and probably
something leaks, but I didn't check for that).
Everything also applies to to timeouts (libvirt_virEventRemoteTimeoutFunc).
--
pozdrawiam / best regards _.-._
Wojtek Porczyk .-^' '^-.
Invisible Things Lab |'-.-^-.-'|
| | | |
I do not fear computers, | '-.-' |
I fear lack of them. '-._ : ,-'
-- Isaac Asimov `^-^-_>
7 years, 6 months
[libvirt] [PATCH] Make use of PERF_COUNT_HW_REF_CPU_CYCLES conditional
by Daniel P. Berrange
The PERF_COUNT_HW_REF_CPU_CYCLES constant is not available
on all Linux distros libvirt targets, so its use must be
made conditional. Other constant have existed long enough
that we can assume they exist, as we don't support very
old distros like RHEL-5 any more.
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
src/util/virperf.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/src/util/virperf.c b/src/util/virperf.c
index 49ec258..f64692b 100644
--- a/src/util/virperf.c
+++ b/src/util/virperf.c
@@ -104,8 +104,14 @@ static struct virPerfEventAttr attrs[] = {
.attrType = PERF_TYPE_HARDWARE,
.attrConfig = PERF_COUNT_HW_STALLED_CYCLES_BACKEND},
{.type = VIR_PERF_EVENT_REF_CPU_CYCLES,
+# ifdef PERF_COUNT_HW_REF_CPU_CYCLES
.attrType = PERF_TYPE_HARDWARE,
- .attrConfig = PERF_COUNT_HW_REF_CPU_CYCLES},
+ .attrConfig = PERF_COUNT_HW_REF_CPU_CYCLES
+# else
+ .attrType = 0,
+ .attrConfig = 0,
+# endif
+ },
};
typedef struct virPerfEventAttr *virPerfEventAttrPtr;
--
2.9.3
7 years, 7 months
[libvirt] [PATCH] network: don't use dhcp-authoritative on static networks
by Martin Wilck
"Static" DHCP networks are those where no dynamic DHCP range is
defined, only a list of host entries is used to serve permanent
IP addresses. On such networks, we don't want dnsmasq to reply
to other requests than those statically defined. But
"dhcp-authoritative" will cause dnsmasq to do just that.
Therefore we can't use "dhcp-authoritative" for static networks.
Fixes: 4ac20b3ae "network: add dnsmasq option 'dhcp-authoritative'"
Signed-off-by: Martin Wilck <mwilck(a)suse.com>
---
src/network/bridge_driver.c | 9 ++++++++-
tests/networkxml2confdata/dhcp6host-routed-network.conf | 1 -
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index ae1589d8c..17c6f3a0f 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -1355,7 +1355,14 @@ networkDnsmasqConfContents(virNetworkObjPtr network,
if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET)) {
if (ipdef->nranges || ipdef->nhosts) {
virBufferAddLit(&configbuf, "dhcp-no-override\n");
- virBufferAddLit(&configbuf, "dhcp-authoritative\n");
+ /*
+ * Use "dhcp-authoritative" only for dynamic DHCP.
+ * In a static-only network, it would cause dnsmasq
+ * to reply to requests from other hosts than those
+ * statically defined.
+ */
+ if (ipdef->nranges || !ipdef->nhosts)
+ virBufferAddLit(&configbuf, "dhcp-authoritative\n");
}
if (ipdef->tftproot) {
diff --git a/tests/networkxml2confdata/dhcp6host-routed-network.conf b/tests/networkxml2confdata/dhcp6host-routed-network.conf
index 87a149880..5728ee430 100644
--- a/tests/networkxml2confdata/dhcp6host-routed-network.conf
+++ b/tests/networkxml2confdata/dhcp6host-routed-network.conf
@@ -10,7 +10,6 @@ bind-dynamic
interface=virbr1
dhcp-range=192.168.122.1,static
dhcp-no-override
-dhcp-authoritative
dhcp-range=2001:db8:ac10:fd01::1,static,64
dhcp-hostsfile=/var/lib/libvirt/dnsmasq/local.hostsfile
addn-hosts=/var/lib/libvirt/dnsmasq/local.addnhosts
--
2.11.0
7 years, 7 months
[libvirt] Proposal PCI/PCIe device placement on PAPR guests
by David Gibson
There was a discussion back in November on the qemu list which spilled
onto the libvirt list about how to add support for PCIe devices to
POWER VMs, specifically 'pseries' machine type PAPR guests.
Here's a more concrete proposal for how to handle part of this in
future from the libvirt side. Strictly speaking what I'm suggesting
here isn't intrinsically linked to PCIe: it will make adding PCIe
support sanely easier, as well as having a number of advantages for
both PCIe and plain-PCI devices on PAPR guests.
Background:
* Currently the pseries machine type only supports vanilla PCI
buses.
* This is a qemu limitation, not something inherent - PAPR guests
running under PowerVM (the IBM hypervisor) can use passthrough
PCIe devices (PowerVM doesn't emulate devices though).
* In fact the way PCI access is para-virtalized in PAPR makes the
usual distinctions between PCI and PCIe largely disappear
* Presentation of PCIe devices to PAPR guests is unusual
* Unlike x86 - and other "bare metal" platforms, root ports are
not made visible to the guest. i.e. all devices (typically)
appear as though they were integrated devices on x86
* In terms of topology all devices will appear in a way similar to
a vanilla PCI bus, even PCIe devices
* However PCIe extended config space is accessible
* This means libvirt's usual placement of PCIe devices is not
suitable for PAPR guests
* PAPR has its own hotplug mechanism
* This is used instead of standard PCIe hotplug
* This mechanism works for both PCIe and vanilla-PCI devices
* This can hotplug/unplug devices even without a root port P2P
bridge between it and the root "bus
* Multiple independent host bridges are routine on PAPR
* Unlike PC (where all host bridges have multiplexed access to
configuration space) PCI host bridges (PHBs) are truly
independent for PAPR guests (disjoint MMIO regions in system
address space)
* PowerVM typically presents a separate PHB to the guest for each
host slot passed through
The Proposal:
I suggest that libvirt implement a new default algorithm for placing
(i.e. assigning addresses to) both PCI and PCIe devices for (only)
PAPR guests.
The short summary is that by default it should assign each device to a
separate vPHB, creating vPHBs as necessary.
* For passthrough sometimes a group of host devices can't be safely
isolated from each other - this is known as a (host) Partitionable
Endpoint (PE). In this case, if any device in the PE is passed
through to a guest, the whole PE must be passed through to the
same vPHB in the guest. From the guest POV, each vPHB has exactly
one (guest) PE.
* To allow for hotplugged devices, libvirt should also add a number
of additional, empty vPHBs (the PAPR spec allows for hotplug of
PHBs, but this is not yet implemented in qemu). When hotplugging
a new device (or PE) libvirt should locate a vPHB which doesn't
currently contain anything.
* libvirt should only (automatically) add PHBs - never root ports or
other PCI to PCI bridges
In order to handle migration, the vPHBs will need to be represented in
the domain XML, which will also allow the user to override this
topology if they want.
Advantages:
There are still some details I need to figure out w.r.t. handling PCIe
devices (on both the qemu and libvirt sides). However the fact that
PAPR guests don't typically see PCIe root ports means that the normal
libvirt PCIe allocation scheme won't work. This scheme has several
advantages with or without support for PCIe devices:
* Better performance for 32-bit devices
With multiple devices on a single vPHB they all must share a (fairly
small) 32-bit DMA/IOMMU window. With separate PHBs they each have a
separate window. PAPR guests have an always-on guest visible IOMMU.
* Better EEH handling for passthrough devices
EEH is an IBM hardware-assisted mechanism for isolating and safely
resetting devices experiencing hardware faults so they don't bring
down other devices or the system at large. It's roughly similar to
PCIe AER in concept, but has a different IBM specific interface, and
works on both PCI and PCIe devices.
Currently the kernel interfaces for handling EEH events on passthrough
devices will only work if there is a single (host) iommu group in the
vfio container. While lifting that restriction would be nice, it's
quite difficult to do so (it requires keeping state synchronized
between multiple host groups). That also means that an EEH error on
one device could stop another device where that isn't required by the
actual hardware.
The unit of EEH isolation is a PE (Partitionable Endpoint) and
currently there is only one guest PE per vPHB. Changing this might
also be possible, but is again quite complex and may result in
confusing and/or broken distinctions between groups for EEH isolation
and IOMMU isolation purposes.
Placing separate host groups in separate vPHBs sidesteps these
problems.
* Guest NUMA node assignment of devices
PAPR does not (and can't reasonably) use the pxb device. Instead to
allocate devices to different guest NUMA nodes they should be placed
on different vPHBs. Placing them on different PHBs by default allows
NUMA node to be assigned to those PHBs in a straightforward manner.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
7 years, 7 months