2009-10-09 20:47:43 +08:00
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
|
|
|
#include "internal.h"
|
|
|
|
#include "testutils.h"
|
|
|
|
#include "network_conf.h"
|
|
|
|
#include "testutilsqemu.h"
|
2013-04-03 18:36:23 +08:00
|
|
|
#include "virstring.h"
|
2009-10-09 20:47:43 +08:00
|
|
|
|
2013-06-07 23:10:28 +08:00
|
|
|
#define VIR_FROM_THIS VIR_FROM_NONE
|
|
|
|
|
2016-04-19 02:18:37 +08:00
|
|
|
typedef enum {
|
|
|
|
TEST_COMPARE_NET_XML2XML_RESULT_SUCCESS,
|
|
|
|
TEST_COMPARE_NET_XML2XML_RESULT_FAIL_PARSE,
|
|
|
|
TEST_COMPARE_NET_XML2XML_RESULT_FAIL_FORMAT,
|
|
|
|
TEST_COMPARE_NET_XML2XML_RESULT_FAIL_COMPARE,
|
|
|
|
} testCompareNetXML2XMLResult;
|
|
|
|
|
2011-04-25 06:25:10 +08:00
|
|
|
static int
|
2011-12-14 18:50:40 +08:00
|
|
|
testCompareXMLToXMLFiles(const char *inxml, const char *outxml,
|
2016-04-19 02:18:37 +08:00
|
|
|
unsigned int flags,
|
|
|
|
testCompareNetXML2XMLResult expectResult)
|
2011-04-25 06:25:10 +08:00
|
|
|
{
|
2009-10-09 20:47:43 +08:00
|
|
|
char *actual = NULL;
|
2016-04-19 02:18:37 +08:00
|
|
|
int ret;
|
2016-04-20 20:36:37 +08:00
|
|
|
testCompareNetXML2XMLResult result = TEST_COMPARE_NET_XML2XML_RESULT_SUCCESS;
|
2009-10-09 20:47:43 +08:00
|
|
|
virNetworkDefPtr dev = NULL;
|
|
|
|
|
2016-04-19 02:18:37 +08:00
|
|
|
if (!(dev = virNetworkDefParseFile(inxml))) {
|
|
|
|
result = TEST_COMPARE_NET_XML2XML_RESULT_FAIL_PARSE;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (expectResult == TEST_COMPARE_NET_XML2XML_RESULT_FAIL_PARSE)
|
|
|
|
goto cleanup;
|
2009-10-09 20:47:43 +08:00
|
|
|
|
2016-04-19 02:18:37 +08:00
|
|
|
if (!(actual = virNetworkDefFormat(dev, flags))) {
|
|
|
|
result = TEST_COMPARE_NET_XML2XML_RESULT_FAIL_FORMAT;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (expectResult == TEST_COMPARE_NET_XML2XML_RESULT_FAIL_FORMAT)
|
|
|
|
goto cleanup;
|
2009-10-09 20:47:43 +08:00
|
|
|
|
2016-05-26 23:01:53 +08:00
|
|
|
if (virTestCompareToFile(actual, outxml) < 0) {
|
2016-04-19 02:18:37 +08:00
|
|
|
result = TEST_COMPARE_NET_XML2XML_RESULT_FAIL_COMPARE;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (expectResult == TEST_COMPARE_NET_XML2XML_RESULT_FAIL_COMPARE)
|
|
|
|
goto cleanup;
|
2009-10-09 20:47:43 +08:00
|
|
|
|
2016-04-19 02:18:37 +08:00
|
|
|
cleanup:
|
|
|
|
if (result == expectResult) {
|
|
|
|
ret = 0;
|
|
|
|
if (expectResult != TEST_COMPARE_NET_XML2XML_RESULT_SUCCESS) {
|
|
|
|
VIR_TEST_DEBUG("Got expected failure code=%d msg=%s",
|
|
|
|
result, virGetLastErrorMessage());
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ret = -1;
|
|
|
|
VIR_TEST_DEBUG("Expected result code=%d but received code=%d",
|
|
|
|
expectResult, result);
|
|
|
|
}
|
|
|
|
virResetLastError();
|
2009-10-09 20:47:43 +08:00
|
|
|
|
2012-02-03 07:16:43 +08:00
|
|
|
VIR_FREE(actual);
|
2009-10-09 20:47:43 +08:00
|
|
|
virNetworkDefFree(dev);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-12-14 18:50:40 +08:00
|
|
|
struct testInfo {
|
|
|
|
const char *name;
|
|
|
|
unsigned int flags;
|
2016-04-19 02:18:37 +08:00
|
|
|
testCompareNetXML2XMLResult expectResult;
|
2011-12-14 18:50:40 +08:00
|
|
|
};
|
|
|
|
|
2011-04-25 06:25:10 +08:00
|
|
|
static int
|
|
|
|
testCompareXMLToXMLHelper(const void *data)
|
|
|
|
{
|
2011-12-14 18:50:40 +08:00
|
|
|
const struct testInfo *info = data;
|
2011-04-25 06:25:10 +08:00
|
|
|
int result = -1;
|
|
|
|
char *inxml = NULL;
|
|
|
|
char *outxml = NULL;
|
|
|
|
|
|
|
|
if (virAsprintf(&inxml, "%s/networkxml2xmlin/%s.xml",
|
2011-12-14 18:50:40 +08:00
|
|
|
abs_srcdir, info->name) < 0 ||
|
2011-04-25 06:25:10 +08:00
|
|
|
virAsprintf(&outxml, "%s/networkxml2xmlout/%s.xml",
|
2011-12-14 18:50:40 +08:00
|
|
|
abs_srcdir, info->name) < 0) {
|
2011-04-25 06:25:10 +08:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2016-04-19 02:18:37 +08:00
|
|
|
result = testCompareXMLToXMLFiles(inxml, outxml, info->flags,
|
|
|
|
info->expectResult);
|
2009-10-09 20:47:43 +08:00
|
|
|
|
2014-03-25 14:53:44 +08:00
|
|
|
cleanup:
|
2012-02-03 07:16:43 +08:00
|
|
|
VIR_FREE(inxml);
|
|
|
|
VIR_FREE(outxml);
|
2011-04-25 06:25:10 +08:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
2009-10-09 20:47:43 +08:00
|
|
|
|
|
|
|
static int
|
2011-04-30 00:21:20 +08:00
|
|
|
mymain(void)
|
2009-10-09 20:47:43 +08:00
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
|
2016-04-19 02:18:37 +08:00
|
|
|
#define DO_TEST_FULL(name, flags, expectResult) \
|
2011-12-14 18:50:40 +08:00
|
|
|
do { \
|
2016-04-19 02:18:37 +08:00
|
|
|
const struct testInfo info = {name, flags, expectResult}; \
|
2016-05-26 23:01:50 +08:00
|
|
|
if (virTestRun("Network XML-2-XML " name, \
|
|
|
|
testCompareXMLToXMLHelper, &info) < 0) \
|
2011-12-14 18:50:40 +08:00
|
|
|
ret = -1; \
|
|
|
|
} while (0)
|
2016-04-19 02:18:37 +08:00
|
|
|
#define DO_TEST(name) \
|
|
|
|
DO_TEST_FULL(name, 0, TEST_COMPARE_NET_XML2XML_RESULT_SUCCESS)
|
|
|
|
#define DO_TEST_FLAGS(name, flags) \
|
|
|
|
DO_TEST_FULL(name, flags, TEST_COMPARE_NET_XML2XML_RESULT_SUCCESS)
|
|
|
|
#define DO_TEST_PARSE_ERROR(name) \
|
|
|
|
DO_TEST_FULL(name, 0, TEST_COMPARE_NET_XML2XML_RESULT_FAIL_PARSE)
|
2009-10-09 20:47:43 +08:00
|
|
|
|
2013-02-16 03:02:26 +08:00
|
|
|
DO_TEST("dhcp6host-routed-network");
|
2012-12-04 00:13:36 +08:00
|
|
|
DO_TEST("empty-allow-ipv6");
|
2009-10-09 20:47:43 +08:00
|
|
|
DO_TEST("isolated-network");
|
|
|
|
DO_TEST("routed-network");
|
|
|
|
DO_TEST("nat-network");
|
|
|
|
DO_TEST("netboot-network");
|
2009-10-28 22:57:49 +08:00
|
|
|
DO_TEST("netboot-proxy-network");
|
2011-06-24 18:04:36 +08:00
|
|
|
DO_TEST("nat-network-dns-txt-record");
|
2013-07-30 20:36:08 +08:00
|
|
|
DO_TEST("nat-network-dns-srv-record");
|
2013-07-29 23:17:47 +08:00
|
|
|
DO_TEST("nat-network-dns-srv-records");
|
2013-07-30 20:36:08 +08:00
|
|
|
DO_TEST("nat-network-dns-srv-record-minimal");
|
2011-06-24 18:04:40 +08:00
|
|
|
DO_TEST("nat-network-dns-hosts");
|
2013-08-14 06:56:38 +08:00
|
|
|
DO_TEST("nat-network-dns-forward-plain");
|
2013-09-14 00:31:07 +08:00
|
|
|
DO_TEST("nat-network-dns-forwarders");
|
2013-09-05 17:08:38 +08:00
|
|
|
DO_TEST("nat-network-forward-nat-address");
|
2015-08-11 21:09:29 +08:00
|
|
|
DO_TEST("nat-network-forward-nat-no-address");
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 11:01:09 +08:00
|
|
|
DO_TEST("8021Qbh-net");
|
|
|
|
DO_TEST("direct-net");
|
|
|
|
DO_TEST("host-bridge-net");
|
|
|
|
DO_TEST("vepa-net");
|
2011-07-22 22:07:28 +08:00
|
|
|
DO_TEST("bandwidth-network");
|
conf: support partially-specified <virtualport> in parser and formatter
Until now, all attributes in a <virtualport> parameter list that were
acceptable for a particular type, were also required. There were no
optional attributes.
One of the aims of supporting <virtualport> in libvirt's virtual
networks and portgroups is to allow specifying the group-wide
parameters in the network's virtualport, and merge that with the
interface's virtualport, which will have the instance-specific info
(i.e. the interfaceid or instanceid).
Additionally, the guest's interface XML shouldn't need to know what
type of network connection will be used prior to runtime - it could be
openvswitch, 802.1Qbh, 802.1Qbg, or none of the above - but should
still be able to specify instance-specific info just in case it turns
out to be applicable.
Finally, up to now, the parser for virtualport has always generated a
random instanceid/interfaceid when appropriate, making it impossible
to leave it blank (which is what's required for virtualports within a
network/portprofile definition).
This patch modifies the parser and formatter of the <virtualport>
element in the following ways:
* because most of the attributes in a virNetDevVPortProfile are fixed
size binary data with no reserved values, there is no way to embed a
"this value wasn't specified" sentinel into the existing data. To
solve this problem, the new *_specified fields in the
virNetDevVPortProfile object that were added in a previous patch of
this series are now set when the corresponding attribute is present
during the parse.
* allow parsing/formatting a <virtualport> that has no type set. In
this case, all fields are settable, but all are also optional.
* add a GENERATE_MISSING_DEFAULTS flag to the parser - if this flag is
set and an instanceid/interfaceid is expected but not provided, a
random one will be generated. This was previously the default
behavior, but is now done only for virtualports inside an
<interface> definition, not for those in <network> or <portgroup>.
* add a REQUIRE_ALL_ATTRIBUTES flag to the parser - if this flag is
set the parser will call the new
virNetDevVPortProfileCheckComplete() functions at the end of the
parser to check for any missing attributes (based on type), and
return failure if anything is missing. This used to be default
behavior. Now it is only used for the virtualport defined inside an
interface's <actual> element (by the time you've figured out the
contents of <actual>, you should have all the necessary data to fill
in the entire virtualport)
* add a REQUIRE_TYPE flag to the parser - if this flag is set, the
parser will return an error if the virtualport has no type
attribute. This also was previously the default behavior, but isn't
needed in the case of the virtualport for a type='network' interface
(i.e. the exact type isn't yet known), or the virtualport of a
portgroup (i.e. the portgroup just has modifiers for the network's
virtualport, which *does* require a type) - in those cases, the
check will be done at domain startup, once the final virtualport is
assembled (this is handled in the next patch).
2012-08-01 02:36:51 +08:00
|
|
|
DO_TEST("openvswitch-net");
|
2016-04-19 02:18:37 +08:00
|
|
|
DO_TEST_FLAGS("passthrough-pf", VIR_NETWORK_XML_INACTIVE);
|
2012-08-16 23:41:41 +08:00
|
|
|
DO_TEST("hostdev");
|
2016-04-19 02:18:37 +08:00
|
|
|
DO_TEST_FLAGS("hostdev-pf", VIR_NETWORK_XML_INACTIVE);
|
2014-08-21 17:06:37 +08:00
|
|
|
DO_TEST("passthrough-address-crash");
|
conf: new network bridge device attribute macTableManager
The macTableManager attribute of a network's bridge subelement tells
libvirt how the bridge's MAC address table (used to determine the
egress port for packets) is managed. In the default mode, "kernel",
management is left to the kernel, which usually determines entries in
part by turning on promiscuous mode on all ports of the bridge,
flooding packets to all ports when the correct destination is unknown,
and adding/removing entries to the fdb as it sees incoming traffic
from particular MAC addresses. In "libvirt" mode, libvirt turns off
learning and flooding on all the bridge ports connected to guest
domain interfaces, and adds/removes entries according to the MAC
addresses in the domain interface configurations. A side effect of
turning off learning and unicast_flood on the ports of a bridge is
that (with Linux kernel 3.17 and newer), the kernel can automatically
turn off promiscuous mode on one or more of the bridge's ports
(usually only the one interface that is used to connect the bridge to
the physical network). The result is better performance (because
packets aren't being flooded to all ports, and can be dropped earlier
when they are of no interest) and slightly better security (a guest
can still send out packets with a spoofed source MAC address, but will
only receive traffic intended for the guest interface's configured MAC
address).
The attribute looks like this in the configuration:
<network>
<name>test</name>
<bridge name='br0' macTableManager='libvirt'/>
...
This patch only adds the config knob, documentation, and test
cases. The functionality behind this knob is added in later patches.
2014-11-21 01:40:33 +08:00
|
|
|
DO_TEST("nat-network-explicit-flood");
|
|
|
|
DO_TEST("host-bridge-no-flood");
|
2016-04-19 03:07:26 +08:00
|
|
|
DO_TEST_PARSE_ERROR("hostdev-duplicate");
|
|
|
|
DO_TEST_PARSE_ERROR("passthrough-duplicate");
|
2016-06-23 06:05:50 +08:00
|
|
|
DO_TEST("metadata");
|
2009-10-09 20:47:43 +08:00
|
|
|
|
2014-03-17 17:38:38 +08:00
|
|
|
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
2009-10-09 20:47:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
VIRT_TEST_MAIN(mymain)
|