[libvirt] [PATCH v2 0/3]add 'sharePolicy' attribute for qemu vnc sharing policy
by Guannan Ren
v1->v2:
changed attribute name from 'policy' to 'sharePolicy'
renamed caps flag name: QEMU_CAPS_VNC_SHARE_POLICY
fixed issues pointed out in v1 review
have to keep hard-coded version probe after checking qemu -help and qmp command.
These patches try to add a new attribute 'sharePolicy' to element graphics of
vnc type. This attribute has three values:
libvirt XML: <graphics type='vnc' port='5900' sharePolicy='allow-exclusive'>
QEMU commandline -vnc :5900,share=allow-exclusive
Allows clients to ask for exclusive access which is
implemented by dropping other connections Connecting
multiple clients in parallel requires all clients asking
for a shared session (vncviewer: -shared switch)
libvirt XML: <graphics type='vnc' port='5900' sharePolicy='force-shared'>
QEMU commandline -vnc :5900,share=force-shared
Disables exclusive client access. Useful for shared
desktop sessions, where you don't want someone forgetting
specify -shared disconnect everybody else.
libvirt XML: <graphics type='vnc' port='5900' sharePolicy='ignore'>
QEMU commandline -vnc :5900,share=ignore
Dompletely ignores the shared flag and allows everybody
connect unconditionally
Guannan Ren(3)
[PATCH v2 1/3] qemu: new vnc display sharing policy caps flag
[PATCH v2 2/3] conf: add 'sharePolicy' attribute to graphics element for vnc
[PATCH v2 3/3] qemu: support share attribute and its values to -vnc
docs/formatdomain.html.in | 13 +++++++++++--
docs/schemas/domaincommon.rng | 9 +++++++++
src/conf/domain_conf.c | 28 ++++++++++++++++++++++++++++
src/conf/domain_conf.h | 11 +++++++++++
src/libvirt_private.syms | 2 ++
src/qemu/qemu_capabilities.c | 12 ++++++++----
src/qemu/qemu_capabilities.h | 1 +
src/qemu/qemu_command.c | 13 +++++++++++++
tests/qemuhelptest.c | 9 ++++++---
tests/qemuxml2argvdata/qemuxml2argv-graphics-vnc-policy.args | 4 ++++
tests/qemuxml2argvdata/qemuxml2argv-graphics-vnc-policy.xml | 35 +++++++++++++++++++++++++++++++++++
tests/qemuxml2argvtest.c | 1 +
12 files changed, 129 insertions(+), 9 deletions(-)
11 years, 6 months
Re: [libvirt] Welcome to the "libvir-list" mailing list
by prakash b
Hi team,
Is libvirt support armv8 architecture.
thanks..
Prakash B
On Tue, May 14, 2013 at 10:42 AM, <libvir-list-request(a)redhat.com> wrote:
> Welcome to the libvir-list(a)redhat.com mailing list!
>
> To post to this list, send your email to:
>
> libvir-list(a)redhat.com
>
> General information about the mailing list is at:
>
> https://www.redhat.com/mailman/listinfo/libvir-list
>
> If you ever want to unsubscribe or change your options (eg, switch to
> or from digest mode, change your password, etc.), visit your
> subscription page at:
>
>
> https://www.redhat.com/mailman/options/libvir-list/bjsprakash%40gmail.com
>
>
> You can also make such adjustments via email by sending a message to:
>
> libvir-list-request(a)redhat.com
>
> with the word `help' in the subject or body (don't include the
> quotes), and you will get back a message with instructions.
>
> You must know your password to change your options (including changing
> the password, itself) or to unsubscribe. It is:
>
> zavoda4
>
> Normally, Mailman will remind you of your redhat.com mailing list
> passwords once every month, although you can disable this if you
> prefer. This reminder will also include instructions on how to
> unsubscribe or change your account options. There is also a button on
> your options page that will email your current password to you.
>
--
pracash
11 years, 6 months
[libvirt] [libvirt-glib PATCHv2 0/6] gconfig: Add classes/methods for snapshot configuration
by Christophe Fergeau
Hey,
This v2 has 3 more patches than the initial series, they were needed to address
various issues with the initial series. 3/6 is not strictly needed, I'm still undecided
as to whether it makes things nicer or not, so it's open for discussion (the deprecation
it introduces would be triggered when building Boxes).
Changes since v1:
- fix a bug in gvir_config_domain_snapshot_get_parent() when the <parent>
element is missing (which happens with the initial snapshot in a given domain)
- add missing gvir_config_domain_snapshot_[gs]et_memory_state() and
gvir_config_domain_snapshot_[gs]et_memory_file()
- return a time_t from gvir_config_domain_snapshot_get_creation_time()
- rename the GVirConfigDomainSnapshotState enum to
GVirConfigDomainSnapshotDomainState
- add a GVirConfigDomainDiskFormat enum and return it from
gvir_config_domain_snapshot_disk_get_driver_type()
Christophe
11 years, 6 months
[libvirt] [libvirt-designer PATCHv2 0/9] Handle more devices in GVirDesignerDomain
by Christophe Fergeau
This goes on top of v2 of the "Improve disk bus type generation" series.
Diff with the previous version is that it's rebased against latest master,
and I've reworked "Implement gvir_designer_domain_add_sound()" patch to
address danpb's comments (gvir_designer_domain_add_sound() is now a public
method that must be called explicitly rather than being implicitly called on
domain creation.
Christophe
11 years, 6 months
[libvirt] [PATCH] build: mark conditionally unused variables
by Eric Blake
These fixes solve a compilation failure on FreeBSD:
util/virnetdevtap.c: In function 'virNetDevTapGetName':
util/virnetdevtap.c:56: warning: unused parameter 'tapfd' [-Wunused-parameter]
util/virnetdevtap.c:56: warning: unused parameter 'ifname' [-Wunused-parameter]
* src/util/virnetdevtap.c (virNetDevTapGetName): Add attributes
when TUNGETIFF is not present.
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
Pushing under the build-breaker rule.
src/util/virnetdevtap.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/util/virnetdevtap.c b/src/util/virnetdevtap.c
index fac95ec..7d77f81 100644
--- a/src/util/virnetdevtap.c
+++ b/src/util/virnetdevtap.c
@@ -53,7 +53,7 @@
* Returns 0 if the interface name is successfully queried, -1 otherwise
*/
int
-virNetDevTapGetName(int tapfd, char **ifname)
+virNetDevTapGetName(int tapfd ATTRIBUTE_UNUSED, char **ifname ATTRIBUTE_UNUSED)
{
#ifdef TUNGETIFF
struct ifreq ifr;
--
1.8.1.4
11 years, 6 months
[libvirt] [PATCH] qemu: fix bad free
by Eric Blake
Commit bd56d0d8 could lead to freeing an uninitialized pointer:
qemu/qemu_monitor_json.c: In function 'qemuMonitorJSONGetCommandLineOptionParameters':
qemu/qemu_monitor_json.c:4284: warning: 'cmd' may be used uninitialized in this function
* src/qemu/qemu_monitor_json.c
(qemuMonitorJSONGetCommandLineOptionParameters): Initialize variable.
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
Pushing under the build-breaker rule (and I _really_ wish you didn't
have to use -O to make gcc raise this sort of warning)
src/qemu/qemu_monitor_json.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 0c011d3..d95198b 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -4281,7 +4281,7 @@ qemuMonitorJSONGetCommandLineOptionParameters(qemuMonitorPtr mon,
char ***params)
{
int ret;
- virJSONValuePtr cmd;
+ virJSONValuePtr cmd = NULL;
virJSONValuePtr reply = NULL;
virJSONValuePtr data = NULL;
virJSONValuePtr array = NULL;
--
1.8.1.4
11 years, 6 months
[libvirt] [PATCH 0/4] prepare for qemu 1.5 command-line probing via QMP
by Eric Blake
This series sets up the groundwork to make it easy to add a
capability bit in qemu_capabilities based on whether a particular
qemu command-line option has a given parameter. Future patches,
such as Osier's work to use '-machine mem-merge' when it exists,
will benefit from this new probing ability.
Since this missed rc1 freeze, I'm a bit reluctant to include it
in libvirt 1.0.5 without a client that actually needs it.
Hmm, in writing up this cover letter, I think I should work on a
patch 5/4 that enhances qemu_capabilities to make it easy to
search for a given option and capability whether parsing -help
output (hello RHEL qemu) or using QMP (upstream).
Eric Blake (4):
json: support removing a value from an object
qemu: use bool in monitor struct
qemu: simplify string cleanup
qemu: query command line options in QMP
src/libvirt_private.syms | 1 +
src/qemu/qemu_domain.c | 7 +-
src/qemu/qemu_domain.h | 2 +-
src/qemu/qemu_monitor.c | 59 ++++++++++++---
src/qemu/qemu_monitor.h | 13 +++-
src/qemu/qemu_monitor_json.c | 174 +++++++++++++++++++++++++++++++++++--------
src/qemu/qemu_monitor_json.h | 4 +
src/qemu/qemu_process.c | 8 +-
src/util/virjson.c | 34 ++++++++-
src/util/virjson.h | 9 ++-
tests/jsontest.c | 83 ++++++++++++++++++++-
tests/qemumonitorjsontest.c | 103 +++++++++++++++++++++++++
tests/qemumonitortestutils.c | 2 +-
13 files changed, 437 insertions(+), 62 deletions(-)
--
1.8.1.4
11 years, 6 months
[libvirt] [PATCH-v5.1] Support for static routes on a virtual bridge
by Gene Czarcinski
network: static route support for <network>
This update includes Laine Stump's comments/suggestions. Once
again he has improved my over-engineered solutions. My original
patch and his patch have been squashed/merged with this being the
result. That plus a little simplified code added to
bridge_driver.c to handle the zero address situations.
This code does not restrict any combination of
address/netmask/prefix for a static route specification. The
metric attribute has been added so that existing route specifications
can be overridden.
Documentation has been updated to reflect a v1.0.6 target.
This patch adds the <route> subelement of <network> to define a static
route. the address and prefix (or netmask) attribute identify the
destination network, and the gateway attribute specifies the next hop
address (which must be directly reachable from the containing
<network>) which is to receive the packets destined for
"address/(prefix|netmask)".
Tests are done to validate that the input definitions are
correct. For example, for a static route ip definition,
the address must be a network address and not a host address.
Additional checks are added to ensure that the specified gateway
is directly reachable via a network defined on this bridge.
The command used is of the following form:
ip route add <address>/<prefix> via <gateway> dev <virbr-bridge> \
proto static metric 1
For family='ipv4' address='0.0.0.0' netmask='0.0.0.0' or prefix='0' is
supported.
For family='ipv6' address='::' prefix=0' is supported.
Anytime an attempt is made to define a static route which duplicates
an existing static route (for example, address=::, prefix=0, metric=1),
the following error message will be sent to syslog:
RTNETLINK answers: File exists
This can be overridden by increasing the value of metric. Caution should
be used when doing this ... especially for a default route.
Note: The use of the command-line interface should be replaced by
direct use of libnl so that error conditions can be handled better. But,
that is being left as an exersize for another day.
.
Signed-off-by: Gene Czarcinski <gene(a)czarc.net>
---
docs/formatnetwork.html.in | 77 +++++
docs/schemas/network.rng | 22 ++
src/conf/network_conf.c | 340 ++++++++++++++++++++-
src/conf/network_conf.h | 22 ++
src/libvirt_private.syms | 1 +
src/network/bridge_driver.c | 64 ++++
src/util/virnetdev.c | 46 +++
src/util/virnetdev.h | 7 +
.../networkxml2xmlin/dhcp6host-routed-network.xml | 2 +
.../networkxml2xmlout/dhcp6host-routed-network.xml | 2 +
10 files changed, 582 insertions(+), 1 deletion(-)
diff --git a/docs/formatnetwork.html.in b/docs/formatnetwork.html.in
index d72bd0a..4c7e74f 100644
--- a/docs/formatnetwork.html.in
+++ b/docs/formatnetwork.html.in
@@ -546,6 +546,56 @@
starting.
</p>
+ <h5><a name="elementsStaticroute">Static Routes</a></h5>
+ <p>
+ Static route definitions are used to provide routing
+ information to the virtualization host for networks which are not
+ defined as a network on one of the virtual bridges so that such
+ networks can be reachable from the virtualization
+ host <span class="since">Since 1.0.6</span>.
+ </p>
+
+ <p>
+ As shown in <a href="formatnetwork.html#examplesNoGateway">this example</a>,
+ it is possible to define a virtual bridge interface with no
+ IPv4 or IPv6 networks. Such interfaces are useful in supporting
+ networks which have no visibility or direct connectivity with the
+ virtualization host, but can be used to support
+ virtual networks which only have guest connectivity. A guest
+ with connectivity to the guest-only network and another network
+ that is directly reachable from the host can act as a gateway between the
+ networks. A static route added to the "visible" network definition
+ provides the routing information so that IP packets can be sent
+ from the virtualization host to guests on the hidden network.
+ </p>
+
+ <p>
+ Here is a fragment of a definition which shows the static
+ route specification as well as the IPv4 and IPv6 definitions
+ for network addresses which are referred to in the
+ <code>gateway</code> gateway address specifications. Note
+ that the third static route specification includes the
+ <code>metric</code> attribute specification with a value of 2.
+ This indicates that this particular definition is overriding another
+ route definition with the same address and prefix but with a lower
+ value for the metric.
+ </p>
+
+ <pre>
+ ...
+ <ip address="192.168.122.1" netmask="255.255.255.0">
+ <dhcp>
+ <range start="192.168.122.128" end="192.168.122.254" />
+ </dhcp>
+ </ip>
+ <route address="192.168.222.0" prefix="24" gateway="192.168.122.2" />
+ <ip family="ipv6" address="2001:db8:ca2:2::1" prefix="64" />
+ <route family="ipv6" address="2001:db8:ca2:3::" prefix="64" gateway="2001:db8:ca2:2::2"/>
+ <route family="ipv6" address="2001:db9:4:1::" prefix="64" gateway="2001:db8:ca2:2::3" metric='2'>
+ </route>
+ ...
+ </pre>
+
<h3><a name="elementsAddress">Addressing</a></h3>
<p>
@@ -577,6 +627,7 @@
</dhcp>
</ip>
<ip family="ipv6" address="2001:db8:ca2:2::1" prefix="64" />
+ <route family="ipv6" address="2001:db9:ca1:1::" prefix="64" gateway="2001:db8:ca2:2::2" />
</network></pre>
<dl>
@@ -826,6 +877,32 @@
</ip>
</network></pre>
+ <p>
+ Below is yet another IPv6 variation. This variation has only IPv6
+ defined with DHCPv6 on the primary IPv6 network. A static link
+ if defined for a second IPv6 network which will not be visable on
+ the bridge interface but will have a static route defined for this
+ network via the specified gateway. Note that the gateway address
+ must be directly reachable via (on the same subnet as) one of the
+ <ip> addresses defined for this <network>.
+ <span class="since">Since 1.0.5</span>
+ </p>
+
+ <pre>
+ <network>
+ <name>net7</name>
+ <bridge name="virbr7" />
+ <forward mode="route"/>
+ <ip family="ipv6" address="2001:db8:ca2:7::1" prefix="64" >
+ <dhcp>
+ <range start="2001:db8:ca2:7::100" end="2001:db8:ca2::1ff" />
+ <host id="0:4:7e:7d:f0:7d:a8:bc:c5:d2:13:32:11:ed:16:ea:84:63" name="lucas" ip="2001:db8:ca2:2:3::4" />
+ </dhcp>
+ </ip>
+ <route family="ipv6" address="2001:db8:ca2:8::" prefix="64" gateway="2001:db8:ca2:7::4" >
+ </route>
+ </network></pre>
+
<h3><a name="examplesPrivate">Isolated network config</a></h3>
<p>
diff --git a/docs/schemas/network.rng b/docs/schemas/network.rng
index 493edae..ded8580 100644
--- a/docs/schemas/network.rng
+++ b/docs/schemas/network.rng
@@ -316,6 +316,28 @@
</optional>
</element>
</zeroOrMore>
+ <!-- <route> element -->
+ <zeroOrMore>
+ <!-- The (static) route element specifies a network address and gateway
+ address to access that network. Both the network address and
+ the gateway address must be specified. -->
+ <element name="route">
+ <optional>
+ <attribute name="family"><ref name="addr-family"/></attribute>
+ </optional>
+ <attribute name="address"><ref name="ipAddr"/></attribute>
+ <optional>
+ <choice>
+ <attribute name="netmask"><ref name="ipv4Addr"/></attribute>
+ <attribute name="prefix"><ref name="ipPrefix"/></attribute>
+ </choice>
+ </optional>
+ <attribute name="gateway"><ref name="ipAddr"/></attribute>
+ <optional>
+ <attribute name="metric"><ref name="unsignedInt"/></attribute>
+ </optional>
+ </element>
+ </zeroOrMore>
</interleave>
</element>
</define>
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index 8abfa53..12ac879 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -143,6 +143,12 @@ virNetworkIpDefClear(virNetworkIpDefPtr def)
}
static void
+virNetworkRouteDefClear(virNetworkRouteDefPtr def)
+{
+ VIR_FREE(def->family);
+}
+
+static void
virNetworkDNSTxtDefClear(virNetworkDNSTxtDefPtr def)
{
VIR_FREE(def->name);
@@ -221,6 +227,11 @@ virNetworkDefFree(virNetworkDefPtr def)
}
VIR_FREE(def->ips);
+ for (ii = 0 ; ii < def->nroutes && def->routes ; ii++) {
+ virNetworkRouteDefClear(&def->routes[ii]);
+ }
+ VIR_FREE(def->routes);
+
for (ii = 0; ii < def->nPortGroups && def->portGroups; ii++) {
virPortGroupDefClear(&def->portGroups[ii]);
}
@@ -1270,6 +1281,219 @@ cleanup:
}
static int
+virNetworkRouteDefParseXML(const char *networkName,
+ xmlNodePtr node,
+ xmlXPathContextPtr ctxt,
+ virNetworkRouteDefPtr def)
+{
+ /*
+ * virNetworkRouteDef object is already allocated as part
+ * of an array. On failure clear: it out, but don't free it.
+ */
+
+ xmlNodePtr save;
+ char *address = NULL, *netmask = NULL;
+ char *gateway = NULL;
+ unsigned long prefix = 0, metric = 0;
+ int result = -1;
+ int prefixRc, metricRc;
+ virSocketAddr testAddr;
+
+ save = ctxt->node;
+ ctxt->node = node;
+
+ /* grab raw data from XML */
+ def->family = virXPathString("string(./@family)", ctxt);
+ address = virXPathString("string(./@address)", ctxt);
+ netmask = virXPathString("string(./@netmask)", ctxt);
+ gateway = virXPathString("string(./@gateway)", ctxt);
+ prefixRc = virXPathULong("string(./@prefix)", ctxt, &prefix);
+ if (prefixRc == -2) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Invalid prefix specified "
+ "in route definition of network '%s'"),
+ networkName);
+ goto cleanup;
+ }
+ def->has_prefix = (prefixRc == 0);
+ def->prefix = prefix;
+ metricRc = virXPathULong("string(./@metric)", ctxt, &metric);
+ if (metricRc == -2) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Invalid metric specified "
+ "in route definition of network '%s'"),
+ networkName);
+ goto cleanup;
+ }
+ def->has_metric = (metricRc == 0);
+ def->metric = metric;
+
+ /* Note: both network and gateway addresses must be specified */
+
+ if (!address) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Missing required address attribute "
+ "in route definition of network '%s'"),
+ networkName);
+ goto cleanup;
+ }
+
+ if (!gateway) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Missing required gateway attribute "
+ "in route definition of network '%s'"),
+ networkName);
+ goto cleanup;
+ }
+
+ if (virSocketAddrParse(&def->address, address, AF_UNSPEC) < 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Bad network address '%s' "
+ "in route definition of network '%s'"),
+ address, networkName);
+ goto cleanup;
+ }
+
+ if (virSocketAddrParse(&def->gateway, gateway, AF_UNSPEC) < 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Bad gateway address '%s' "
+ "in route definition of network '%s'"),
+ gateway, networkName);
+ goto cleanup;
+ }
+
+ /* validate network address, etc. for each family */
+ if ((def->family == NULL) || (STREQ(def->family, "ipv4"))) {
+ if (!(VIR_SOCKET_ADDR_IS_FAMILY(&def->address, AF_INET) ||
+ VIR_SOCKET_ADDR_IS_FAMILY(&def->address, AF_UNSPEC))) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("%s family specified for non-IPv4 address '%s' "
+ "in route definition of network '%s'"),
+ def->family == NULL? "no" : "ipv4",
+ address, networkName);
+ goto cleanup;
+ }
+ if (!VIR_SOCKET_ADDR_IS_FAMILY(&def->gateway, AF_INET)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("%s family specified for non-IPv4 gateway '%s' "
+ "in route definition of network '%s'"),
+ def->family == NULL? "no" : "ipv4",
+ address, networkName);
+ goto cleanup;
+ }
+ if (netmask) {
+ if (virSocketAddrParse(&def->netmask, netmask, AF_UNSPEC) < 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Bad netmask address '%s' "
+ "in route definition of network '%s'"),
+ netmask, networkName);
+ goto cleanup;
+ }
+ if (!VIR_SOCKET_ADDR_IS_FAMILY(&def->netmask, AF_INET)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("network '%s' has invalid netmask '%s' "
+ "for address '%s' (both must be IPv4)"),
+ networkName, netmask, address);
+ goto cleanup;
+ }
+ if (def->has_prefix) {
+ /* can't have both netmask and prefix at the same time */
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("route definition '%s' cannot have both "
+ "a prefix and a netmask"),
+ networkName);
+ goto cleanup;
+ }
+ }
+ if (def->prefix > 32) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Invalid IPv4 prefix %u for '%s' specified "
+ "in route definition of network '%s'"),
+ def->prefix,
+ def->family == NULL? "no" : "ipv4", networkName);
+ goto cleanup;
+ }
+ } else if (STREQ(def->family, "ipv6")) {
+ if (!VIR_SOCKET_ADDR_IS_FAMILY(&def->address, AF_INET6)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("ipv6 family specified for non-IPv6 address '%s' "
+ "in route definition of network '%s'"),
+ address, networkName);
+ goto cleanup;
+ }
+ if (netmask) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("specifying netmask invalid for IPv6 address '%s' "
+ "in route definition of network '%s'"),
+ address, networkName);
+ goto cleanup;
+ }
+ if (!VIR_SOCKET_ADDR_IS_FAMILY(&def->gateway, AF_INET6)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("ipv6 specified for non-IPv6 gateway address '%s' "
+ "in route definition of network '%s'"),
+ gateway, networkName);
+ goto cleanup;
+ }
+ if (def->prefix > 128) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Invalid IPv6 prefix %u for '%s' specified "
+ "in route definition of network '%s'"),
+ def->prefix, def->family, networkName);
+ goto cleanup;
+ }
+ } else {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Unrecognized family '%s' "
+ "in route definition of network'%s'"),
+ def->family, networkName);
+ goto cleanup;
+ }
+
+ /* make sure the address is a network address */
+ if (netmask) {
+ if (virSocketAddrMask(&def->address, &def->netmask, &testAddr) < 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("error converting address '%s' with netmask '%s' "
+ "to network-address "
+ "in route definition of network '%s'"),
+ address, netmask, networkName);
+ goto cleanup;
+ }
+ } else {
+ if (virSocketAddrMaskByPrefix(&def->address,
+ def->prefix, &testAddr) < 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("error converting address '%s' with prefix %u "
+ "to network-address "
+ "in route definition of network '%s'"),
+ address, def->prefix, networkName);
+ goto cleanup;
+ }
+ }
+ if (!virSocketAddrEqual(&def->address, &testAddr)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("address '%s' in route definition of network '%s' "
+ "is not a network address"),
+ address, networkName);
+ goto cleanup;
+ }
+
+ result = 0;
+
+cleanup:
+ if (result < 0) {
+ virNetworkRouteDefClear(def);
+ }
+ VIR_FREE(address);
+ VIR_FREE(netmask);
+ VIR_FREE(gateway);
+
+ ctxt->node = save;
+ return result;
+}
+
+static int
virNetworkPortGroupParseXML(virPortGroupDefPtr def,
xmlNodePtr node,
xmlXPathContextPtr ctxt)
@@ -1684,8 +1908,9 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
char *tmp;
char *stp = NULL;
xmlNodePtr *ipNodes = NULL;
+ xmlNodePtr *routeNodes = NULL;
xmlNodePtr *portGroupNodes = NULL;
- int nIps, nPortGroups;
+ int nIps, nPortGroups, nRoutes;
xmlNodePtr dnsNode = NULL;
xmlNodePtr virtPortNode = NULL;
xmlNodePtr forwardNode = NULL;
@@ -1839,6 +2064,68 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
}
VIR_FREE(ipNodes);
+ nRoutes = virXPathNodeSet("./route", ctxt, &routeNodes);
+ if (nRoutes < 0)
+ goto error;
+
+ if (nRoutes > 0) {
+ int ii;
+
+ /* allocate array to hold all the route definitions */
+ if (VIR_ALLOC_N(def->routes, nRoutes) < 0) {
+ virReportOOMError();
+ goto error;
+ }
+ /* parse each definition */
+ for (ii = 0; ii < nRoutes; ii++) {
+ int ret = virNetworkRouteDefParseXML(def->name, routeNodes[ii],
+ ctxt, &def->routes[ii]);
+ if (ret < 0)
+ goto error;
+ def->nroutes++;
+ }
+
+ /* now validate the correctness of any static route gateways specified
+ *
+ * note: the parameters within each definition are verified/assumed valid;
+ * the question being asked and answered here is if the specified gateway
+ * is directly reachable from this bridge.
+ */
+ nRoutes = def->nroutes;
+ nIps = def->nips;
+ for (ii = 0; ii < nRoutes; ii++) {
+ int jj;
+ virSocketAddr testAddr, testGw;
+ bool addrMatch;
+ virNetworkRouteDefPtr gwdef = &def->routes[ii];
+ addrMatch = false;
+ for (jj = 0; jj < nIps; jj++) {
+ virNetworkIpDefPtr def2 = &def->ips[jj];
+ if (VIR_SOCKET_ADDR_FAMILY(&gwdef->gateway)
+ != VIR_SOCKET_ADDR_FAMILY(&def2->address)) {
+ continue;
+ }
+ int prefix = virNetworkIpDefPrefix(def2);
+ virSocketAddrMaskByPrefix(&def2->address, prefix, &testAddr);
+ virSocketAddrMaskByPrefix(&gwdef->gateway, prefix, &testGw);
+ if (VIR_SOCKET_ADDR_VALID(&testAddr) &&
+ VIR_SOCKET_ADDR_VALID(&testGw) &&
+ virSocketAddrEqual(&testAddr, &testGw)) {
+ addrMatch = true;
+ break;
+ }
+ }
+ if (!addrMatch) {
+ char *gw = virSocketAddrFormat(&gwdef->gateway);
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unreachable static route gateway '%s' specified for network '%s'"),
+ gw, def->name);
+ VIR_FREE(gw);
+ goto error;
+ }
+ }
+ }
+
forwardNode = virXPathNode("./forward", ctxt);
if (forwardNode &&
virNetworkForwardDefParseXML(def->name, forwardNode, ctxt, &def->forward) < 0) {
@@ -1911,6 +2198,7 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
return def;
error:
+ VIR_FREE(routeNodes);
VIR_FREE(stp);
virNetworkDefFree(def);
VIR_FREE(ipNodes);
@@ -2136,6 +2424,51 @@ error:
}
static int
+virNetworkRouteDefFormat(virBufferPtr buf,
+ const virNetworkRouteDefPtr def)
+{
+ int result = -1;
+
+ virBufferAddLit(buf, "<route");
+
+ if (def->family) {
+ virBufferAsprintf(buf, " family='%s'", def->family);
+ }
+ if (VIR_SOCKET_ADDR_VALID(&def->address)) {
+ char *addr = virSocketAddrFormat(&def->address);
+ if (!addr)
+ goto error;
+ virBufferAsprintf(buf, " address='%s'", addr);
+ VIR_FREE(addr);
+ }
+ if (VIR_SOCKET_ADDR_VALID(&def->netmask)) {
+ char *addr = virSocketAddrFormat(&def->netmask);
+ if (!addr)
+ goto error;
+ virBufferAsprintf(buf, " netmask='%s'", addr);
+ VIR_FREE(addr);
+ }
+ if (def->has_prefix) {
+ virBufferAsprintf(buf," prefix='%u'", def->prefix);
+ }
+ if (VIR_SOCKET_ADDR_VALID(&def->gateway)) {
+ char *addr = virSocketAddrFormat(&def->gateway);
+ if (!addr)
+ goto error;
+ virBufferAsprintf(buf, " gateway='%s'", addr);
+ VIR_FREE(addr);
+ }
+ if (def->has_metric && def->metric > 0) {
+ virBufferAsprintf(buf," metric='%u'", def->metric);
+ }
+ virBufferAddLit(buf, "/>\n");
+
+ result = 0;
+error:
+ return result;
+}
+
+static int
virPortGroupDefFormat(virBufferPtr buf,
const virPortGroupDefPtr def)
{
@@ -2347,6 +2680,11 @@ virNetworkDefFormatInternal(virBufferPtr buf,
goto error;
}
+ for (ii = 0; ii < def->nroutes; ii++) {
+ if (virNetworkRouteDefFormat(buf, &def->routes[ii]) < 0)
+ goto error;
+ }
+
if (virNetDevVPortProfileFormat(def->virtPortProfile, buf) < 0)
goto error;
diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h
index e187f05..43f80d4 100644
--- a/src/conf/network_conf.h
+++ b/src/conf/network_conf.h
@@ -149,6 +149,25 @@ struct _virNetworkIpDef {
virSocketAddr bootserver;
};
+typedef struct _virNetworkRouteDef virNetworkRouteDef;
+typedef virNetworkRouteDef *virNetworkRouteDefPtr;
+struct _virNetworkRouteDef {
+ char *family; /* ipv4 or ipv6 - default is ipv4 */
+ virSocketAddr address; /* Routed Network IP address */
+
+ /* One or the other of the following two will be used for a given
+ * Network address, but never both. The parser guarantees this.
+ * The virSocketAddrGetIpPrefix() can be used to get a
+ * valid prefix.
+ */
+ virSocketAddr netmask; /* ipv4 - either netmask or prefix specified */
+ unsigned int prefix; /* ipv6 - only prefix allowed */
+ bool has_prefix; /* prefix= was specified */
+ unsigned int metric; /* value for metric (defaults to 1) */
+ bool has_metric; /* metric= was specified */
+ virSocketAddr gateway; /* gateway IP address for ip-route */
+ };
+
typedef struct _virNetworkForwardIfDef virNetworkForwardIfDef;
typedef virNetworkForwardIfDef *virNetworkForwardIfDefPtr;
struct _virNetworkForwardIfDef {
@@ -224,6 +243,9 @@ struct _virNetworkDef {
size_t nips;
virNetworkIpDefPtr ips; /* ptr to array of IP addresses on this network */
+ size_t nroutes;
+ virNetworkRouteDefPtr routes; /* ptr to array of static routes on this interface */
+
virNetworkDNSDef dns; /* dns related configuration */
virNetDevVPortProfilePtr virtPortProfile;
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index d4cb4a3..dfa4779 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1463,6 +1463,7 @@ virMacAddrSetRaw;
# util/virnetdev.h
+virNetDevAddRoute;
virNetDevClearIPv4Address;
virNetDevExists;
virNetDevGetIndex;
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 9c5a8ae..4392e20 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -2391,6 +2391,7 @@ out:
return ret;
}
+/* add an IP address to a bridge */
static int
networkAddAddrToBridge(virNetworkObjPtr network,
virNetworkIpDefPtr ipdef)
@@ -2411,6 +2412,55 @@ networkAddAddrToBridge(virNetworkObjPtr network,
return 0;
}
+/* add an IP (static) route to a bridge */
+static int
+networkAddRouteToBridge(virNetworkObjPtr network,
+ virNetworkRouteDefPtr routedef)
+{
+ int prefix = 0;
+ unsigned int metric;
+ virSocketAddrPtr addr = &routedef->address;
+ virSocketAddrPtr mask = &routedef->netmask;
+ virSocketAddr zero;
+
+ /* this creates an all-0 address of the appropriate family */
+ ignore_value(virSocketAddrParse(&zero,
+ (VIR_SOCKET_ADDR_IS_FAMILY(addr,AF_INET)
+ ? "0.0.0.0" : "::"),
+ VIR_SOCKET_ADDR_FAMILY(addr)));
+
+ if (virSocketAddrEqual(addr, &zero)) {
+ if (routedef->has_prefix && routedef->prefix == 0)
+ prefix = 0;
+ else if ((VIR_SOCKET_ADDR_IS_FAMILY(mask, AF_INET) &&
+ virSocketAddrEqual(mask, &zero)))
+ prefix = 0;
+ else
+ prefix = virSocketAddrGetIpPrefix(addr, mask, routedef->prefix);
+ } else {
+ prefix = virSocketAddrGetIpPrefix(addr, mask, routedef->prefix);
+ }
+
+ if (prefix < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("network '%s' has an invalid netmask "
+ "or IP address in route definition"),
+ network->def->name);
+ return -1;
+ }
+
+ if (routedef->has_metric && routedef->metric > 0)
+ metric = routedef->metric;
+ else
+ metric = 1;
+
+ if (virNetDevAddRoute(network->def->bridge, &routedef->address,
+ prefix, &routedef->gateway, metric) < 0) {
+ return -1;
+ }
+ return 0;
+}
+
static int
networkStartNetworkVirtual(struct network_driver *driver,
virNetworkObjPtr network)
@@ -2419,6 +2469,7 @@ networkStartNetworkVirtual(struct network_driver *driver,
bool v4present = false, v6present = false;
virErrorPtr save_err = NULL;
virNetworkIpDefPtr ipdef;
+ virNetworkRouteDefPtr routedef;
char *macTapIfName = NULL;
int tapfd = -1;
@@ -2495,6 +2546,19 @@ networkStartNetworkVirtual(struct network_driver *driver,
if (virNetDevSetOnline(network->def->bridge, 1) < 0)
goto err2;
+ for (ii = 0; ii < network->def->nroutes; ii++) {
+ routedef = &network->def->routes[ii];
+ /* Add the IP route to the bridge */
+ /* ignore errors, error msg will be generated */
+ /* but libvirt will not know and net-destroy will work. */
+ if (VIR_SOCKET_ADDR_VALID(&routedef->gateway)) {
+ if (networkAddRouteToBridge(network, routedef) < 0) {
+ /* an error occurred adding the static route */
+ continue; /* for now, do nothing */
+ }
+ }
+ }
+
/* If forward.type != NONE, turn on global IP forwarding */
if (network->def->forward.type != VIR_NETWORK_FORWARD_NONE &&
networkEnableIpForwarding(v4present, v6present) < 0) {
diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c
index d987b8e..01aaff1 100644
--- a/src/util/virnetdev.c
+++ b/src/util/virnetdev.c
@@ -783,6 +783,52 @@ cleanup:
}
/**
+ * virNetDevSetGateway:
+ * @ifname: the interface name
+ * @addr: the IP network address (IPv4 or IPv6)
+ * @prefix: number of 1 bits in the netmask
+ * @gateway: via address for route (same as @addr)
+ *
+ * Add a route for a network IP address to an interface. This function
+ * *does not* remove any previously added IP static routes.
+ *
+ * Returns 0 in case of success or -1 in case of error.
+ */
+
+int
+virNetDevAddRoute(const char *ifname,
+ virSocketAddrPtr addr,
+ unsigned int prefix,
+ virSocketAddrPtr gateway,
+ unsigned int metric)
+{
+ virCommandPtr cmd = NULL;
+ char *addrstr = NULL, *gatewaystr = NULL;
+ int ret = -1;
+
+ if (!(addrstr = virSocketAddrFormat(addr)))
+ goto cleanup;
+ if (!(gatewaystr = virSocketAddrFormat(gateway)))
+ goto cleanup;
+ cmd = virCommandNew(IP_PATH);
+ virCommandAddArgList(cmd, "route", "add", NULL);
+ virCommandAddArgFormat(cmd, "%s/%u", addrstr, prefix);
+ virCommandAddArgList(cmd, "via", gatewaystr, "dev", ifname,
+ "proto", "static", "metric", NULL);
+ virCommandAddArgFormat(cmd, "%u", metric);
+
+ if (virCommandRun(cmd, NULL) < 0)
+ goto cleanup;
+
+ ret = 0;
+cleanup:
+ VIR_FREE(addrstr);
+ VIR_FREE(gatewaystr);
+ virCommandFree(cmd);
+ return ret;
+}
+
+/**
* virNetDevClearIPv4Address:
* @ifname: the interface name
* @addr: the IP address (IPv4 or IPv6)
diff --git a/src/util/virnetdev.h b/src/util/virnetdev.h
index 551ea22..0b394ad 100644
--- a/src/util/virnetdev.h
+++ b/src/util/virnetdev.h
@@ -42,6 +42,13 @@ int virNetDevSetIPv4Address(const char *ifname,
virSocketAddr *addr,
unsigned int prefix)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
+int virNetDevAddRoute(const char *ifname,
+ virSocketAddrPtr addr,
+ unsigned int prefix,
+ virSocketAddrPtr gateway,
+ unsigned int metric)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(4)
+ ATTRIBUTE_NONNULL(5) ATTRIBUTE_RETURN_CHECK;
int virNetDevClearIPv4Address(const char *ifname,
virSocketAddr *addr,
unsigned int prefix)
diff --git a/tests/networkxml2xmlin/dhcp6host-routed-network.xml b/tests/networkxml2xmlin/dhcp6host-routed-network.xml
index 2693d87..40f6dfe 100644
--- a/tests/networkxml2xmlin/dhcp6host-routed-network.xml
+++ b/tests/networkxml2xmlin/dhcp6host-routed-network.xml
@@ -19,4 +19,6 @@
<host id='0:1:0:1:18:aa:62:fe:0:16:3e:44:55:66' name='badbob' ip='2001:db8:ac10:fd01::1:24' />
</dhcp>
</ip>
+ <route address="192.168.222.0" netmask="255.255.255.0" gateway="192.168.122.10"/>
+ <route family="ipv6" address="2001:db8:ac10:fc00::" prefix="64" gateway="2001:db8:ac10:fd01::1:24"/>
</network>
diff --git a/tests/networkxml2xmlout/dhcp6host-routed-network.xml b/tests/networkxml2xmlout/dhcp6host-routed-network.xml
index 1d3035b..fc8666b 100644
--- a/tests/networkxml2xmlout/dhcp6host-routed-network.xml
+++ b/tests/networkxml2xmlout/dhcp6host-routed-network.xml
@@ -21,4 +21,6 @@
<host id='0:1:0:1:18:aa:62:fe:0:16:3e:44:55:66' name='badbob' ip='2001:db8:ac10:fd01::1:24' />
</dhcp>
</ip>
+ <route address='192.168.222.0' netmask='255.255.255.0' gateway='192.168.122.10'/>
+ <route family='ipv6' address='2001:db8:ac10:fc00::' prefix='64' gateway='2001:db8:ac10:fd01::1:24'/>
</network>
--
1.8.1.4
11 years, 6 months
[libvirt] [PATCH 0/4] Extra validation for the <sysinfo> section
by John Ferlan
Not necessary for 1.0.5, but figured I'd put it out there now.
https://bugzilla.redhat.com/show_bug.cgi?id=890494
The <sysinfo> section needs an extra uuid validation check. The current
check compares the numerical sysinfo/system_uuid with the domain uuid;
however, it's possible that someone added extra hyphens into the sysinfo
uuid which results in the inability to start the domain (at least qemu).
The bug report indicates the 'date' field should at least be syntax checked
based on what's desribed in the SMBIOS spec. From the spec:
"String number of the BIOS release date. The date string, if supplied, is
in either mm/dd/yy or mm/dd/yyyy format. If the year portion of the string
is two digits, the year is assumed to be 19yy.
NOTE: The mm/dd/yyyy format is required for SMBIOS version 2.3 and later"
John Ferlan (4):
docs: Fix syntax in sysinfo description
docs: Update description of SMBIOS fields
Validate the bios_date format for <sysinfo>
Need better validation of <sysinfo> uuid
docs/formatdomain.html.in | 51 ++++++++++++++++++++++++++++++++++++++---------
src/conf/domain_conf.c | 47 +++++++++++++++++++++++++++++++++++++++----
2 files changed, 85 insertions(+), 13 deletions(-)
--
1.8.1.4
11 years, 6 months
[libvirt] [PATCH] build: avoid shadowed variable in fdstreamtest
by Eric Blake
On RHEL 6.4 (gcc 4.4.7), I got:
fdstreamtest.c: In function 'testFDStreamReadCommon':
fdstreamtest.c:44: error: declaration of 'tmpfile' shadows a global declaration [-Wshadow]
* tests/fdstreamtest.c (testFDStreamReadCommon)
(testFDStreamWriteCommon): Rename 'tmpfile' variable.
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
Pushing under the build-breaker rule.
tests/fdstreamtest.c | 28 ++++++++++++++--------------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/tests/fdstreamtest.c b/tests/fdstreamtest.c
index cda2689..9f780c9 100644
--- a/tests/fdstreamtest.c
+++ b/tests/fdstreamtest.c
@@ -41,7 +41,7 @@
static int testFDStreamReadCommon(const char *scratchdir, bool blocking)
{
int fd = -1;
- char *tmpfile = NULL;
+ char *file = NULL;
int ret = -1;
char *pattern = NULL;
char *buf = NULL;
@@ -63,10 +63,10 @@ static int testFDStreamReadCommon(const char *scratchdir, bool blocking)
for (i = 0 ; i < PATTERN_LEN ; i++)
pattern[i] = i;
- if (virAsprintf(&tmpfile, "%s/input.data", scratchdir) < 0)
+ if (virAsprintf(&file, "%s/input.data", scratchdir) < 0)
goto cleanup;
- if ((fd = open(tmpfile, O_CREAT|O_WRONLY|O_EXCL, 0600)) < 0)
+ if ((fd = open(file, O_CREAT|O_WRONLY|O_EXCL, 0600)) < 0)
goto cleanup;
for (i = 0 ; i < 10 ; i++) {
@@ -83,7 +83,7 @@ static int testFDStreamReadCommon(const char *scratchdir, bool blocking)
/* Start reading 1/2 way through first pattern
* and end 1/2 way through last pattern
*/
- if (virFDStreamOpenFile(st, tmpfile,
+ if (virFDStreamOpenFile(st, file,
PATTERN_LEN / 2, PATTERN_LEN * 9,
O_RDONLY) < 0)
goto cleanup;
@@ -149,11 +149,11 @@ cleanup:
if (st)
virStreamFree(st);
VIR_FORCE_CLOSE(fd);
- if (tmpfile != NULL)
- unlink(tmpfile);
+ if (file != NULL)
+ unlink(file);
if (conn)
virConnectClose(conn);
- VIR_FREE(tmpfile);
+ VIR_FREE(file);
VIR_FREE(pattern);
VIR_FREE(buf);
return ret;
@@ -173,7 +173,7 @@ static int testFDStreamReadNonblock(const void *data)
static int testFDStreamWriteCommon(const char *scratchdir, bool blocking)
{
int fd = -1;
- char *tmpfile = NULL;
+ char *file = NULL;
int ret = -1;
char *pattern = NULL;
char *buf = NULL;
@@ -195,7 +195,7 @@ static int testFDStreamWriteCommon(const char *scratchdir, bool blocking)
for (i = 0 ; i < PATTERN_LEN ; i++)
pattern[i] = i;
- if (virAsprintf(&tmpfile, "%s/input.data", scratchdir) < 0)
+ if (virAsprintf(&file, "%s/input.data", scratchdir) < 0)
goto cleanup;
if (!(st = virStreamNew(conn, flags)))
@@ -204,7 +204,7 @@ static int testFDStreamWriteCommon(const char *scratchdir, bool blocking)
/* Start writing 1/2 way through first pattern
* and end 1/2 way through last pattern
*/
- if (virFDStreamCreateFile(st, tmpfile,
+ if (virFDStreamCreateFile(st, file,
PATTERN_LEN / 2, PATTERN_LEN * 9,
O_WRONLY, 0600) < 0)
goto cleanup;
@@ -244,7 +244,7 @@ static int testFDStreamWriteCommon(const char *scratchdir, bool blocking)
goto cleanup;
}
- if ((fd = open(tmpfile, O_RDONLY)) < 0)
+ if ((fd = open(file, O_RDONLY)) < 0)
goto cleanup;
for (i = 0 ; i < 10 ; i++) {
@@ -292,11 +292,11 @@ cleanup:
if (st)
virStreamFree(st);
VIR_FORCE_CLOSE(fd);
- if (tmpfile != NULL)
- unlink(tmpfile);
+ if (file != NULL)
+ unlink(file);
if (conn)
virConnectClose(conn);
- VIR_FREE(tmpfile);
+ VIR_FREE(file);
VIR_FREE(pattern);
VIR_FREE(buf);
return ret;
--
1.8.1.4
11 years, 6 months