Devel
Threads by month
- ----- 2026 -----
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- 29 participants
- 40117 discussions
[libvirt] [PATCH] qemu: Fix the wrong logic of building cmd line for volume type disk
by Osier Yang 16 Oct '13
by Osier Yang 16 Oct '13
16 Oct '13
It builds a "libiscsi" uri if the volume type is "file" and
"disk->auth.username" is specified, but I even see no reason to
build the "libiscsi" uri for a "file" type volume, and the logic
to check whether "disk->auth.username" is specified is also beyond
understanding.
It produces unexpected result like below:
Disk config (pool is of 'fs' type):
<disk type='volume' device='disk'>
<driver name='qemu' type='raw'/>
<auth username='myuser'>
</auth>
<source pool='default' volume='f18.img'/>
<target dev='sda' bus='scsi'/>
<address type='drive' controller='0' bus='0' target='0' unit='0'/>
</disk>
% virsh start f18
error: Failed to start domain f18
error: internal error: iscsi accepts only one host
---
src/qemu/qemu_command.c | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index abb62e9..9b6a27d 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -3806,13 +3806,7 @@ qemuBuildVolumeString(virConnectPtr conn,
}
break;
case VIR_STORAGE_VOL_FILE:
- if (disk->auth.username) {
- if (qemuBuildISCSIString(conn, disk, opt) < 0)
- goto cleanup;
- virBufferAddChar(opt, ',');
- } else {
- virBufferEscape(opt, ',', ",", "file=%s,", disk->src);
- }
+ virBufferEscape(opt, ',', ",", "file=%s,", disk->src);
break;
case VIR_STORAGE_VOL_NETWORK:
/* Keep the compiler quite, qemuTranslateDiskSourcePool already
--
1.8.1.4
2
1
From: "Daniel P. Berrange" <berrange(a)redhat.com>
The previous OOM testing support would re-run the entire "main"
method each iteration, failing a different malloc each time.
When a test suite has 'n' allocations, the number of repeats
requires is (n * (n + 1) ) / 2. This gets very large, very
quickly.
This new OOM testing support instead integrates at the
virtTestRun level, so each individual test case gets repeated,
instead of the entire test suite. This means the values of
'n' are orders of magnitude smaller.
The simple usage is
$ VIR_TEST_OOM=1 ./qemuxml2argvtest
...
29) QEMU XML-2-ARGV clock-utc ... OK
Test OOM for nalloc=36 .................................... OK
30) QEMU XML-2-ARGV clock-localtime ... OK
Test OOM for nalloc=36 .................................... OK
31) QEMU XML-2-ARGV clock-france ... OK
Test OOM for nalloc=38 ...................................... OK
...
the second lines reports how many mallocs have to be failed, and thus
how many repeats of the test will be run.
If it crashes, then running under valgrind will often show the problem
$ VIR_TEST_OOM=1 ../run valgrind ./qemuxml2argvtest
When debugging problems it is also helpful to select an individual
test case
$ VIR_TEST_RANGE=30 VIR_TEST_OOM=1 ../run valgrind ./qemuxml2argvtest
When things get really tricky, it is possible to request that just
specific allocs are failed. eg to fail allocs 5 -> 12, use
$ VIR_TEST_RANGE=30 VIR_TEST_OOM=1:5-12 ../run valgrind ./qemuxml2argvtest
In the worse case, you might want to know the stack trace of the
alloc which was failed then VIR_TEST_OOM_TRACE can be set. If it
is set to 1 then it will only print if it thinks a mistake happened.
This is often not reliable, so setting it to 2 will make it print
the stack trace for every alloc that is failed.
$ VIR_TEST_OOM_TRACE=2 VIR_TEST_RANGE=30 VIR_TEST_OOM=1:5-5 ../run valgrind ./qemuxml2argvtest
30) QEMU XML-2-ARGV clock-localtime ... OK
Test OOM for nalloc=36 !virAllocN
/home/berrange/src/virt/libvirt/src/util/viralloc.c:180
virHashCreateFull
/home/berrange/src/virt/libvirt/src/util/virhash.c:144
virDomainDefParseXML
/home/berrange/src/virt/libvirt/src/conf/domain_conf.c:11745
virDomainDefParseNode
/home/berrange/src/virt/libvirt/src/conf/domain_conf.c:12646
virDomainDefParse
/home/berrange/src/virt/libvirt/src/conf/domain_conf.c:12590
testCompareXMLToArgvFiles
/home/berrange/src/virt/libvirt/tests/qemuxml2argvtest.c:106
virtTestRun
/home/berrange/src/virt/libvirt/tests/testutils.c:250
mymain
/home/berrange/src/virt/libvirt/tests/qemuxml2argvtest.c:418 (discriminator 2)
virtTestMain
/home/berrange/src/virt/libvirt/tests/testutils.c:750
??
??:0
_start
??:?
FAILED
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
docs/internals/oomtesting.html.in | 213 ++++++++++++++++++++++++++++++++++++++
docs/sitemap.html.in | 4 +
tests/qemuargv2xmltest.c | 14 +--
tests/qemuxml2argvtest.c | 12 ++-
tests/qemuxmlnstest.c | 18 ++--
tests/testutils.c | 195 +++++++++++++++++++++++++++++++++-
tests/testutils.h | 2 +
7 files changed, 437 insertions(+), 21 deletions(-)
create mode 100644 docs/internals/oomtesting.html.in
diff --git a/docs/internals/oomtesting.html.in b/docs/internals/oomtesting.html.in
new file mode 100644
index 0000000..652aff6
--- /dev/null
+++ b/docs/internals/oomtesting.html.in
@@ -0,0 +1,213 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <body>
+ <h1>Out of memory testing</h1>
+
+ <ul id="toc"></ul>
+
+
+ <p>
+ This page describes how to use the test suite todo out of memory
+ testing.
+ </p>
+
+ <h2>Building with OOM testing</h2>
+
+ <p>
+ Since OOM testing requires hooking into the malloc APIs, it is
+ not enabled by default. The flag <code>--enable-test-oom</code>
+ must be given to <code>configure</code>. When this is done the
+ libvirt allocation APIs will have some hooks enabled.
+ </p>
+
+ <pre>
+$ ./configure --enable-test-oom
+</pre>
+
+
+ <h2><a name="basicoom">Basic OOM testing support</a></h2>
+
+ <p>
+ The first step in validating OOM usage is to run a test suite
+ with full OOM testing enabled. This is done by setting the
+ <code>VIR_TEST_OOM=1</code> environment variable. The way this
+ works is that it runs the test once normally to "prime" any
+ static memory allocations. Then it runs it once more counting
+ the total number of memory allocations. Then it runs it in a
+ loop failing a different memory allocation each time. For every
+ memory allocation failure triggered, it expects the test case
+ to return an error. OOM testing is quite slow requiring each
+ test case to be executed O(n) times, where 'n' is the total
+ number of memory allocations. This results in a total number
+ of memory allocations of '(n * (n + 1) ) / 2'
+ </p>
+
+ <pre>
+$ VIR_TEST_OOM=1 ./qemuxml2argvtest
+ 1) QEMU XML-2-ARGV minimal ... OK
+ Test OOM for nalloc=42 .......................................... OK
+ 2) QEMU XML-2-ARGV minimal-s390 ... OK
+ Test OOM for nalloc=28 ............................ OK
+ 3) QEMU XML-2-ARGV machine-aliases1 ... OK
+ Test OOM for nalloc=38 ...................................... OK
+ 4) QEMU XML-2-ARGV machine-aliases2 ... OK
+ Test OOM for nalloc=38 ...................................... OK
+ 5) QEMU XML-2-ARGV machine-core-on ... OK
+ Test OOM for nalloc=37 ..................................... OK
+...snip...
+</pre>
+
+ <p>
+ In this output, the first line shows the normal execution and
+ the test number, and the second line shows the total number
+ of memory allocations from that test case.
+ </p>
+
+ <h3><a name="valgrind">Tracking failures with valgrind</a></h3>
+
+ <p>
+ The test suite should obviously *not* crash during OOM testing.
+ If it does crash, then to assist in tracking down the problem
+ it is worth using valgrind and only running a single test case.
+ For example, supposing test case 5 crashed. Then re-run the
+ test with
+ </p>
+
+ <pre>
+$ VIR_TEST_OOM=1 VIR_TEST_RANGE=5 ../run valgrind ./qemuxml2argvtest
+...snip...
+ 5) QEMU XML-2-ARGV machine-core-on ... OK
+ Test OOM for nalloc=37 ..................................... OK
+...snip...
+ </pre>
+
+ <p>
+ Valgrind should report the cause of the crash - for example a
+ double free or use of uninitialized memory or NULL pointer
+ access.
+ </p>
+
+ <h3><a name="stacktraces">Tracking failures with stack traces</a></h3>
+
+ <p>
+ With some really difficult bugs valgrind is not sufficient to
+ identify the cause. In this case, it is useful to identify the
+ precise allocation which was failed, to allow the code path
+ to the error to be traced. The <code>VIR_TEST_OOM</code>
+ env variable can be given a range of memory allocations to
+ test. So if a test case has 150 allocations, it can be told
+ to only test allocation numbers 7-10. The <code>VIR_TEST_OOM_TRACE</code>
+ variable can be used to print out stack traces.
+ </p>
+
+ <pre>
+$ VIR_TEST_OOM_TRACE=2 VIR_TEST_OOM=1:7-10 VIR_TEST_RANGE=5 \
+ ../run valgrind ./qemuxml2argvtest
+ 5) QEMU XML-2-ARGV machine-core-on ... OK
+ Test OOM for nalloc=37 !virAllocN
+/home/berrange/src/virt/libvirt/src/util/viralloc.c:180
+virDomainDefParseXML
+/home/berrange/src/virt/libvirt/src/conf/domain_conf.c:11786 (discriminator 1)
+virDomainDefParseNode
+/home/berrange/src/virt/libvirt/src/conf/domain_conf.c:12677
+virDomainDefParse
+/home/berrange/src/virt/libvirt/src/conf/domain_conf.c:12621
+testCompareXMLToArgvFiles
+/home/berrange/src/virt/libvirt/tests/qemuxml2argvtest.c:107
+virtTestRun
+/home/berrange/src/virt/libvirt/tests/testutils.c:266
+mymain
+/home/berrange/src/virt/libvirt/tests/qemuxml2argvtest.c:388 (discriminator 2)
+virtTestMain
+/home/berrange/src/virt/libvirt/tests/testutils.c:791
+__libc_start_main
+??:?
+_start
+??:?
+!virAlloc
+/home/berrange/src/virt/libvirt/src/util/viralloc.c:133
+virDomainDiskDefParseXML
+/home/berrange/src/virt/libvirt/src/conf/domain_conf.c:4790
+virDomainDefParseXML
+/home/berrange/src/virt/libvirt/src/conf/domain_conf.c:11797
+virDomainDefParseNode
+/home/berrange/src/virt/libvirt/src/conf/domain_conf.c:12677
+virDomainDefParse
+/home/berrange/src/virt/libvirt/src/conf/domain_conf.c:12621
+testCompareXMLToArgvFiles
+/home/berrange/src/virt/libvirt/tests/qemuxml2argvtest.c:107
+virtTestRun
+/home/berrange/src/virt/libvirt/tests/testutils.c:266
+mymain
+/home/berrange/src/virt/libvirt/tests/qemuxml2argvtest.c:388 (discriminator 2)
+virtTestMain
+/home/berrange/src/virt/libvirt/tests/testutils.c:791
+__libc_start_main
+??:?
+_start
+??:?
+!virAllocN
+/home/berrange/src/virt/libvirt/src/util/viralloc.c:180
+virXPathNodeSet
+/home/berrange/src/virt/libvirt/src/util/virxml.c:609
+virDomainDefParseXML
+/home/berrange/src/virt/libvirt/src/conf/domain_conf.c:11805
+virDomainDefParseNode
+/home/berrange/src/virt/libvirt/src/conf/domain_conf.c:12677
+virDomainDefParse
+/home/berrange/src/virt/libvirt/src/conf/domain_conf.c:12621
+testCompareXMLToArgvFiles
+/home/berrange/src/virt/libvirt/tests/qemuxml2argvtest.c:107
+virtTestRun
+/home/berrange/src/virt/libvirt/tests/testutils.c:266
+mymain
+/home/berrange/src/virt/libvirt/tests/qemuxml2argvtest.c:388 (discriminator 2)
+virtTestMain
+/home/berrange/src/virt/libvirt/tests/testutils.c:791
+__libc_start_main
+??:?
+_start
+??:?
+!virAllocN
+/home/berrange/src/virt/libvirt/src/util/viralloc.c:180
+virDomainDefParseXML
+/home/berrange/src/virt/libvirt/src/conf/domain_conf.c:11808 (discriminator 1)
+virDomainDefParseNode
+/home/berrange/src/virt/libvirt/src/conf/domain_conf.c:12677
+virDomainDefParse
+/home/berrange/src/virt/libvirt/src/conf/domain_conf.c:12621
+testCompareXMLToArgvFiles
+/home/berrange/src/virt/libvirt/tests/qemuxml2argvtest.c:107
+virtTestRun
+/home/berrange/src/virt/libvirt/tests/testutils.c:266
+mymain
+/home/berrange/src/virt/libvirt/tests/qemuxml2argvtest.c:388 (discriminator 2)
+virtTestMain
+/home/berrange/src/virt/libvirt/tests/testutils.c:791
+__libc_start_main
+??:?
+_start
+??:?
+ </pre>
+
+ <h3><a name="noncrash">Non-crash related problems</a></h3>
+
+ <p>
+ Not all memory allocation bugs result in code crashing. Sometimes
+ the code will be silently ignoring the allocation failure, resulting
+ in incorrect data being produced. For example the XML parser may
+ mistakenly treat an allocation failure as indicating that an XML
+ attribute was not set in the input document. It is hard to identify
+ these problems from the test suite automatically. For this, the
+ test suites should be run with <code>VIR_TEST_DEBUG=1</code> set
+ and then stderr analysed for any unexpected data. For example,
+ the XML conversion may show an embedded "(null)" literal, or the
+ test suite might complain about missing elements / attributes
+ in the actual vs expected data. These are all signs of bugs in
+ OOM handling. In the future the OOM tests will be enhanced to
+ validate that an error VIR_ERR_NO_MEMORY is returned for each
+ allocation failed, rather than some other error.
+ </p>
+ </body>
+</html>
diff --git a/docs/sitemap.html.in b/docs/sitemap.html.in
index d821a9e..d885f02 100644
--- a/docs/sitemap.html.in
+++ b/docs/sitemap.html.in
@@ -338,6 +338,10 @@
<a href="internals/locking.html">Lock managers</a>
<span>Use lock managers to protect disk content</span>
</li>
+ <li>
+ <a href="internals/oomtesting.html">Out of memory testing</a>
+ <span>Simulating OOM conditions in the test suite</span>
+ </li>
</ul>
</li>
<li>
diff --git a/tests/qemuargv2xmltest.c b/tests/qemuargv2xmltest.c
index 6dd8bb0..92fc89a 100644
--- a/tests/qemuargv2xmltest.c
+++ b/tests/qemuargv2xmltest.c
@@ -42,7 +42,6 @@ static int testCompareXMLToArgvFiles(const char *xml,
char *cmd = NULL;
int ret = -1;
virDomainDefPtr vmdef = NULL;
- char *log;
if (virtTestLoadFile(cmdfile, &cmd) < 0)
goto fail;
@@ -53,13 +52,16 @@ static int testCompareXMLToArgvFiles(const char *xml,
cmd, NULL, NULL, NULL)))
goto fail;
- if ((log = virtTestLogContentAndReset()) == NULL)
- goto fail;
- if ((*log != '\0') != expect_warning) {
+ if (!virtTestOOMActive()) {
+ char *log;
+ if ((log = virtTestLogContentAndReset()) == NULL)
+ goto fail;
+ if ((*log != '\0') != expect_warning) {
+ VIR_FREE(log);
+ goto fail;
+ }
VIR_FREE(log);
- goto fail;
}
- VIR_FREE(log);
if (!(actualxml = virDomainDefFormat(vmdef, 0)))
goto fail;
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 060acf2..83ddbad 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -107,7 +107,8 @@ static int testCompareXMLToArgvFiles(const char *xml,
if (!(vmdef = virDomainDefParseFile(xml, driver.caps, driver.xmlopt,
QEMU_EXPECTED_VIRT_TYPES,
VIR_DOMAIN_XML_INACTIVE))) {
- if (flags & FLAG_EXPECT_PARSE_ERROR)
+ if (!virtTestOOMActive() &&
+ (flags & FLAG_EXPECT_PARSE_ERROR))
goto ok;
goto out;
}
@@ -170,7 +171,8 @@ static int testCompareXMLToArgvFiles(const char *xml,
migrateFrom, migrateFd, NULL,
VIR_NETDEV_VPORT_PROFILE_OP_NO_OP,
&testCallbacks))) {
- if (flags & FLAG_EXPECT_FAILURE) {
+ if (!virtTestOOMActive() &&
+ (flags & FLAG_EXPECT_FAILURE)) {
ret = 0;
if (virTestGetDebug() > 1)
fprintf(stderr, "Got expected error: %s\n",
@@ -184,7 +186,8 @@ static int testCompareXMLToArgvFiles(const char *xml,
goto out;
}
- if (!!virGetLastError() != !!(flags & FLAG_EXPECT_ERROR)) {
+ if (!virtTestOOMActive() &&
+ (!!virGetLastError() != !!(flags & FLAG_EXPECT_ERROR))) {
if (virTestGetDebug() && (log = virtTestLogContentAndReset()))
fprintf(stderr, "\n%s", log);
goto out;
@@ -205,7 +208,8 @@ static int testCompareXMLToArgvFiles(const char *xml,
}
ok:
- if (flags & FLAG_EXPECT_ERROR) {
+ if (!virtTestOOMActive() &&
+ (flags & FLAG_EXPECT_ERROR)) {
/* need to suppress the errors */
virResetLastError();
}
diff --git a/tests/qemuxmlnstest.c b/tests/qemuxmlnstest.c
index 2cc15d1..38c98bd 100644
--- a/tests/qemuxmlnstest.c
+++ b/tests/qemuxmlnstest.c
@@ -117,15 +117,17 @@ static int testCompareXMLToArgvFiles(const char *xml,
&testCallbacks)))
goto fail;
- if (!!virGetLastError() != expectError) {
- if (virTestGetDebug() && (log = virtTestLogContentAndReset()))
- fprintf(stderr, "\n%s", log);
- goto fail;
- }
+ if (!virtTestOOMActive()) {
+ if (!!virGetLastError() != expectError) {
+ if (virTestGetDebug() && (log = virtTestLogContentAndReset()))
+ fprintf(stderr, "\n%s", log);
+ goto fail;
+ }
- if (expectError) {
- /* need to suppress the errors */
- virResetLastError();
+ if (expectError) {
+ /* need to suppress the errors */
+ virResetLastError();
+ }
}
if (!(actualargv = virCommandToString(cmd)))
diff --git a/tests/testutils.c b/tests/testutils.c
index 5d634b4..bc1e34e 100644
--- a/tests/testutils.c
+++ b/tests/testutils.c
@@ -47,6 +47,13 @@
#include "virprocess.h"
#include "virstring.h"
+#ifdef TEST_OOM
+# ifdef TEST_OOM_TRACE
+#include <dlfcn.h>
+#include <execinfo.h>
+# endif
+#endif
+
#ifdef HAVE_PATHS_H
# include <paths.h>
#endif
@@ -64,6 +71,18 @@ static unsigned int testDebug = -1;
static unsigned int testVerbose = -1;
static unsigned int testExpensive = -1;
+#ifdef TEST_OOM
+static unsigned int testOOM = 0;
+static unsigned int testOOMStart = -1;
+static unsigned int testOOMEnd = -1;
+static unsigned int testOOMTrace = 0;
+# ifdef TEST_OOM_TRACE
+void *testAllocStack[30];
+int ntestAllocStack;
+# endif
+#endif
+static bool testOOMActive = false;
+
static size_t testCounter = 0;
static size_t testStart = 0;
static size_t testEnd = 0;
@@ -71,6 +90,19 @@ static size_t testEnd = 0;
char *progname;
char *abs_srcdir;
+bool virtTestOOMActive(void)
+{
+ return testOOMActive;
+}
+
+#ifdef TEST_OOM_TRACE
+static void virTestAllocHook(int nalloc ATTRIBUTE_UNUSED,
+ void *opaque ATTRIBUTE_UNUSED)
+{
+ ntestAllocStack = backtrace(testAllocStack, ARRAY_CARDINALITY(testAllocStack));
+}
+#endif
+
void virtTestResult(const char *name, int ret, const char *msg, ...)
{
va_list vargs;
@@ -109,6 +141,35 @@ void virtTestResult(const char *name, int ret, const char *msg, ...)
va_end(vargs);
}
+#ifdef TEST_OOM_TRACE
+static void
+virTestShowTrace(void)
+{
+ size_t j;
+ for (j = 2; j < ntestAllocStack; j++) {
+ Dl_info info;
+ char *cmd;
+
+ dladdr(testAllocStack[j], &info);
+ if (info.dli_fname &&
+ strstr(info.dli_fname, ".so")) {
+ if (virAsprintf(&cmd, "addr2line -f -e %s %p",
+ info.dli_fname,
+ ((void*)((unsigned long long)testAllocStack[j]
+ - (unsigned long long)info.dli_fbase))) < 0)
+ continue;
+ } else {
+ if (virAsprintf(&cmd, "addr2line -f -e %s %p",
+ (char*)(info.dli_fname ? info.dli_fname : "<unknown>"),
+ testAllocStack[j]) < 0)
+ continue;
+ }
+ ignore_value(system(cmd));
+ VIR_FREE(cmd);
+ }
+}
+#endif
+
/*
* Runs test
*
@@ -155,7 +216,7 @@ virtTestRun(const char *title,
!((testCounter-1) % 40)) {
fprintf(stderr, " %-3zu\n", (testCounter-1));
fprintf(stderr, " ");
- }
+ }
if (ret == 0)
fprintf(stderr, ".");
else if (ret == EXIT_AM_SKIP)
@@ -164,6 +225,77 @@ virtTestRun(const char *title,
fprintf(stderr, "!");
}
+#ifdef TEST_OOM
+ if (testOOM && ret != EXIT_AM_SKIP) {
+ int nalloc;
+ int oomret;
+ int start, end;
+ size_t i;
+ virResetLastError();
+ virAllocTestInit();
+# ifdef TEST_OOM_TRACE
+ virAllocTestHook(virTestAllocHook, NULL);
+# endif
+ oomret = body(data);
+ nalloc = virAllocTestCount();
+ fprintf(stderr, " Test OOM for nalloc=%d ", nalloc);
+ if (testOOMStart == -1 ||
+ testOOMEnd == -1) {
+ start = 0;
+ end = nalloc;
+ } else {
+ start = testOOMStart;
+ end = testOOMEnd + 1;
+ }
+ testOOMActive = true;
+ for (i = start; i < end; i++) {
+ bool missingFail = false;
+# ifdef TEST_OOM_TRACE
+ memset(testAllocStack, 0, ARRAY_CARDINALITY(testAllocStack));
+ ntestAllocStack = 0;
+# endif
+ virAllocTestOOM(i + 1, 1);
+ oomret = body(data);
+
+ /* fprintf() disabled because XML parsing APIs don't allow
+ * distinguish between element / attribute not present
+ * in the XML (which is non-fatal), vs OOM / malformed
+ * which should be fatal. Thus error reporting for
+ * optionally present XML is mostly broken.
+ */
+ if (oomret == 0) {
+ missingFail = true;
+# if 0
+ fprintf(stderr, " alloc %zu failed but no err status\n", i + 1);
+# endif
+ } else {
+ virErrorPtr lerr = virGetLastError();
+ if (!lerr) {
+# if 0
+ fprintf(stderr, " alloc %zu failed but no error report\n", i + 1);
+# endif
+ missingFail = true;
+ }
+ }
+ if ((missingFail && testOOMTrace) || (testOOMTrace > 1)) {
+ fprintf(stderr, "%s", "!");
+# ifdef TEST_OOM_TRACE
+ virTestShowTrace();
+# endif
+ ret = -1;
+ } else {
+ fprintf(stderr, "%s", ".");
+ }
+ }
+ testOOMActive = false;
+ if (ret == 0)
+ fprintf(stderr, " OK\n");
+ else
+ fprintf(stderr, " FAILED\n");
+ virAllocTestInit();
+ }
+#endif /* TEST_OOM */
+
return ret;
}
@@ -192,7 +324,6 @@ virtTestLoadFile(const char *file, char **buf)
tmplen = buflen = st.st_size + 1;
if (VIR_ALLOC_N(*buf, buflen) < 0) {
- fprintf(stderr, "%s: larger than available memory (> %d)\n", file, buflen);
VIR_FORCE_FCLOSE(fp);
return -1;
}
@@ -468,7 +599,8 @@ virtTestLogOutput(virLogSource source ATTRIBUTE_UNUSED,
{
struct virtTestLogData *log = data;
virCheckFlags(VIR_LOG_STACK_TRACE,);
- virBufferAsprintf(&log->buf, "%s: %s", timestamp, str);
+ if (!testOOMActive)
+ virBufferAsprintf(&log->buf, "%s: %s", timestamp, str);
}
static void
@@ -537,6 +669,9 @@ int virtTestMain(int argc,
int ret;
bool abs_srcdir_cleanup = false;
char *testRange = NULL;
+#ifdef TEST_OOM
+ char *oomstr;
+#endif
abs_srcdir = getenv("abs_srcdir");
if (!abs_srcdir) {
@@ -597,6 +732,60 @@ int virtTestMain(int argc,
}
}
+#ifdef TEST_OOM
+ if ((oomstr = getenv("VIR_TEST_OOM")) != NULL) {
+ char *next;
+ if (testDebug == -1)
+ testDebug = 1;
+ testOOM = 1;
+ if (oomstr[0] != '\0' &&
+ oomstr[1] == ':') {
+ if (virStrToLong_ui(oomstr + 2, &next, 10, &testOOMStart) < 0) {
+ fprintf(stderr, "Cannot parse range %s\n", oomstr);
+ return EXIT_FAILURE;
+ }
+ if (*next == '\0') {
+ testOOMEnd = testOOMStart;
+ } else {
+ if (*next != '-') {
+ fprintf(stderr, "Cannot parse range %s\n", oomstr);
+ return EXIT_FAILURE;
+ }
+ if (virStrToLong_ui(next+1, NULL, 10, &testOOMEnd) < 0) {
+ fprintf(stderr, "Cannot parse range %s\n", oomstr);
+ return EXIT_FAILURE;
+ }
+ }
+ } else {
+ testOOMStart = -1;
+ testOOMEnd = -1;
+ }
+ }
+
+# ifdef TEST_OOM_TRACE
+ if ((oomstr = getenv("VIR_TEST_OOM_TRACE")) != NULL) {
+ if (virStrToLong_ui(oomstr, NULL, 10, &testOOMTrace) < 0) {
+ fprintf(stderr, "Cannot parse oom trace %s\n", oomstr);
+ return EXIT_FAILURE;
+ }
+ }
+# else
+ if (getenv("VIR_TEST_OOM_TRACE")) {
+ fprintf(stderr, "%s", "OOM test tracing not enabled in this build\n");
+ return EXIT_FAILURE;
+ }
+# endif
+#else /* TEST_OOM */
+ if (getenv("VIR_TEST_OOM")) {
+ fprintf(stderr, "%s", "OOM testing not enabled in this build\n");
+ return EXIT_FAILURE;
+ }
+ if (getenv("VIR_TEST_OOM_TRACE")) {
+ fprintf(stderr, "%s", "OOM test tracing not enabled in this build\n");
+ return EXIT_FAILURE;
+ }
+#endif /* TEST_OOM */
+
ret = (func)();
if (abs_srcdir_cleanup)
diff --git a/tests/testutils.h b/tests/testutils.h
index 478b53c..e6f494d 100644
--- a/tests/testutils.h
+++ b/tests/testutils.h
@@ -40,6 +40,8 @@
extern char *progname;
extern char *abs_srcdir;
+bool virtTestOOMActive(void);
+
void virtTestResult(const char *name, int ret, const char *msg, ...)
ATTRIBUTE_FMT_PRINTF(3,4);
int virtTestRun(const char *title,
--
1.8.3.1
1
0
[libvirt] [PATCH 0/6] Try to fix selinux/securityfs mount handling in LXC
by Daniel P. Berrange 16 Oct '13
by Daniel P. Berrange 16 Oct '13
16 Oct '13
From: "Daniel P. Berrange" <berrange(a)redhat.com>
This series tries to address the problem of LXC containers failing
to start because 'securityfs' is not compiled in. In doing this some
general cleanup was performed on the LXC mount code.
Daniel P. Berrange (6):
Add virFileIsMountPoint function
Remove unused 'opts' field from LXC basic mounts struct
Remove pointless 'srcpath' variable in lxcContainerMountBasicFS
Remove duplicate entries in lxcBasicMounts array
Add flag to lxcBasicMounts to control use in user namespaces
Skip any files which are not mounted on the host
src/libvirt_private.syms | 1 +
src/lxc/lxc_container.c | 86 +++++++++++++++++++++++++++++-------------------
src/util/virfile.c | 58 ++++++++++++++++++++++++++++++++
src/util/virfile.h | 2 ++
4 files changed, 113 insertions(+), 34 deletions(-)
--
1.8.3.1
4
16
[libvirt] [PATCHv2 00/23] Better approach to add the "pvticketlocks" feature
by Peter Krempa 16 Oct '13
by Peter Krempa 16 Oct '13
16 Oct '13
This version resolves conflicts with Eric's const correctnes series.
The paravirtual spinlock feature was introduced recently into the qemu and
linux code base. To test it you need the most recent -rc version of the linux
kernel and the git version of qemu.
As the requirements to activate this feature in the guest are really volatile
(kernel support, qemu support .. .) I decided to improve the original version
so that it detects if the feature was actually enabled in the guest. This
avoids possible problems with breaking guest ABI when migrating between two
hosts with different kernels. Additionally we may start enforcin other features
too.
This patchset is partialy based on Jiri's work on getting actual cpu definition
from a running qemu.
Jiri Denemark (8):
cpu: Add support for loading and storing CPU data
cpu: x86: Rename struct cpuX86cpuid as virCPUx86CPUID
cpu: x86: Rename struct cpuX86Data as virCPUx86Data
cpu: x86: Rename x86DataFree() as virCPUx86DataFree()
cpu: x86: Rename x86MakeCPUData as virCPUx86MakeData
cpu: x86: Rename x86DataAddCpuid as virCPUx86DataAddCPUID
cpu: Export few x86-specific APIs
qemu: Add monitor APIs to fetch CPUID data from QEMU
Peter Krempa (15):
schema: Rename option to make it reusable
conf: Clean up few error messages
qemu: command: Fix macro indentation
cpu: x86: Rename data_iterator and DATA_ITERATOR_INIT
cpu: x86: Fix return types of x86cpuidMatch and x86cpuidMatchMasked
cpu: x86: Fix function header formatting and whitespace
cpu: x86: Use whitespace to clarify context and use consistent labels
cpu: x86: Clean up error messages in x86VendorLoad()
qemu: Clean up check of maximum cpu count supported by a machine type
cpu_x86: Refactor storage of CPUID data to add support for KVM
features
cpu: x86: Parse the CPU feature map only once
cpu: x86: Add internal CPUID features support and KVM feature bits
conf: Refactor storing and usage of feature flags
qemu: Add support for paravirtual spinlocks in the guest
qemu: process: Validate specific CPUID flags of a guest
docs/formatdomain.html.in | 7 +
docs/schemas/domaincommon.rng | 18 +-
src/conf/domain_conf.c | 200 ++++--
src/conf/domain_conf.h | 3 +-
src/cpu/cpu.c | 41 ++
src/cpu/cpu.h | 16 +-
src/cpu/cpu_x86.c | 699 ++++++++++++---------
src/cpu/cpu_x86.h | 9 +
src/cpu/cpu_x86_data.h | 26 +-
src/libvirt_private.syms | 8 +
src/libxl/libxl_conf.c | 9 +-
src/lxc/lxc_container.c | 6 +-
src/qemu/qemu_command.c | 31 +-
src/qemu/qemu_monitor.c | 21 +
src/qemu/qemu_monitor.h | 3 +
src/qemu/qemu_monitor_json.c | 107 ++++
src/qemu/qemu_monitor_json.h | 3 +
src/qemu/qemu_process.c | 50 +-
src/vbox/vbox_tmpl.c | 45 +-
src/xenapi/xenapi_driver.c | 10 +-
src/xenapi/xenapi_utils.c | 22 +-
src/xenxs/xen_sxpr.c | 20 +-
src/xenxs/xen_xm.c | 30 +-
tests/Makefile.am | 1 +
.../qemumonitorjson-getcpu-empty.data | 2 +
.../qemumonitorjson-getcpu-empty.json | 46 ++
.../qemumonitorjson-getcpu-filtered.data | 4 +
.../qemumonitorjson-getcpu-filtered.json | 46 ++
.../qemumonitorjson-getcpu-full.data | 5 +
.../qemumonitorjson-getcpu-full.json | 46 ++
.../qemumonitorjson-getcpu-host.data | 6 +
.../qemumonitorjson-getcpu-host.json | 45 ++
tests/qemumonitorjsontest.c | 76 +++
.../qemuxml2argv-pv-spinlock-disabled.args | 5 +
.../qemuxml2argv-pv-spinlock-disabled.xml | 26 +
.../qemuxml2argv-pv-spinlock-enabled.args | 5 +
.../qemuxml2argv-pv-spinlock-enabled.xml | 26 +
tests/qemuxml2argvtest.c | 2 +
tests/qemuxml2xmltest.c | 2 +
39 files changed, 1279 insertions(+), 448 deletions(-)
create mode 100644 tests/qemumonitorjsondata/qemumonitorjson-getcpu-empty.data
create mode 100644 tests/qemumonitorjsondata/qemumonitorjson-getcpu-empty.json
create mode 100644 tests/qemumonitorjsondata/qemumonitorjson-getcpu-filtered.data
create mode 100644 tests/qemumonitorjsondata/qemumonitorjson-getcpu-filtered.json
create mode 100644 tests/qemumonitorjsondata/qemumonitorjson-getcpu-full.data
create mode 100644 tests/qemumonitorjsondata/qemumonitorjson-getcpu-full.json
create mode 100644 tests/qemumonitorjsondata/qemumonitorjson-getcpu-host.data
create mode 100644 tests/qemumonitorjsondata/qemumonitorjson-getcpu-host.json
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-disabled.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-disabled.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-enabled.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-enabled.xml
--
1.8.3.2
3
50
[libvirt] [PATCH] virprocess: make virProcessGetStartTime work on Mac OS X
by Ryota Ozaki 16 Oct '13
by Ryota Ozaki 16 Oct '13
16 Oct '13
This patch addresses the following warning output by libvirtd:
warning : virProcessGetStartTime:843 : Process start time of
pid XXXXX not available on this platform
For Mac OS X, we can use similar instructions to FreeBSD
to get the start time of a process. The difference between them
is struct kinfo_proc; kinfo_proc.ki_start is the start time
of a process for FreeBSD while kinfo_proc.kp_proc.p_starttime
for Mac OS X.
Note that this patch works for Lion and Mountain Lion, however,
doesn't work for Snow Leopard for some reason;
sysctlnametomib("kern.proc.pid", ...) fails on Snow Leopard with
the following error:
error : virProcessGetStartTime:822 : Unable to get MIB of
kern.proc.pid: No such file or directory
This is unexpected. man 3 sysctl of Snow Leopard says it
should work...
Anyway libvirtd is able to launch on Snow Leopard regardless of
the error.
Signed-off-by: Ryota Ozaki <ozaki.ryota(a)gmail.com>
---
src/util/virprocess.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/src/util/virprocess.c b/src/util/virprocess.c
index 9fc3207..5a0ed0d 100644
--- a/src/util/virprocess.c
+++ b/src/util/virprocess.c
@@ -32,7 +32,7 @@
#endif
#include <sched.h>
-#ifdef __FreeBSD__
+#if defined(__FreeBSD__) || defined(__APPLE__)
# include <sys/param.h>
# include <sys/sysctl.h>
# include <sys/user.h>
@@ -809,7 +809,7 @@ cleanup:
VIR_FREE(buf);
return ret;
}
-#elif defined(__FreeBSD__)
+#elif defined(__FreeBSD__) || defined(__APPLE__)
int virProcessGetStartTime(pid_t pid,
unsigned long long *timestamp)
{
@@ -817,7 +817,12 @@ int virProcessGetStartTime(pid_t pid,
int mib[4];
size_t len = 4;
- sysctlnametomib("kern.proc.pid", mib, &len);
+ /* FIXME: It doesn't work on Snow Leopard for some reason */
+ if (sysctlnametomib("kern.proc.pid", mib, &len) < 0) {
+ virReportSystemError(errno, "%s",
+ _("Unable to get MIB of kern.proc.pid"));
+ return -1;
+ }
len = sizeof(struct kinfo_proc);
mib[3] = pid;
@@ -828,7 +833,11 @@ int virProcessGetStartTime(pid_t pid,
return -1;
}
+# if defined(__FreeBSD__)
*timestamp = (unsigned long long)p.ki_start.tv_sec;
+# else
+ *timestamp = (unsigned long long)p.kp_proc.p_starttime.tv_sec;
+# endif
return 0;
--
1.8.4
2
2
From: Chen Hanxiao <chenhanxiao(a)cn.fujitsu.com>
Since 2.6.39, kernel changed the minimum weight of device blkio
while libvirt hard-coded the value range checking.
So we should leave the job of checking to kernel.
Chen Hanxiao (3):
[libvirt]docs: change the minimum weight description for blkio
[libvirt]cgroup: show error when EINVAL caught
[libvirt]cgroup: leave value checking to kernel
docs/formatdomain.html.in | 6 ++++--
src/util/vircgroup.c | 26 +++++++++++---------------
tools/virsh.pod | 11 ++++++-----
3 files changed, 21 insertions(+), 22 deletions(-)
--
1.8.2.1
2
7
[libvirt] [PATCH v3]LXC: Helper function for checking permission of dir when userns enabled
by Chen Hanxiao 16 Oct '13
by Chen Hanxiao 16 Oct '13
16 Oct '13
From: Chen Hanxiao <chenhanxiao(a)cn.fujitsu.com>
If we enable userns, the process with uid/gid in idmap
should have enough permission to access dir we provided
for containers.
Currently, the debug log is very implicit
or misleading sometimes.
This patch will help clarify this for us
when using debug log or virsh.
v2: syntax-check clean
v3: reliable method for checking permission of dir
Signed-off-by: Chen Hanxiao <chenhanxiao(a)cn.fujitsu.com>
---
src/lxc/lxc_container.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 88 insertions(+)
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index 8abaea0..9a05e30 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -110,6 +110,13 @@ struct __lxc_child_argv {
int handshakefd;
};
+typedef struct __lxc_userns_DirPermCheck_argv lxc_userns_DirPermCheck_argv_t;
+struct __lxc_userns_DirPermCheck_argv {
+ uid_t uid;
+ gid_t gid;
+ virDomainDefPtr vmDef;
+};
+
static int lxcContainerMountFSBlock(virDomainFSDefPtr fs,
const char *srcprefix);
@@ -1829,6 +1836,84 @@ lxcNeedNetworkNamespace(virDomainDefPtr def)
return false;
}
+static
+int lxcContainerCheckDirPermissionChild(void *argv)
+{
+ size_t i;
+ lxc_userns_DirPermCheck_argv_t *args = argv;
+ uid_t uid = args->uid;
+ uid_t gid = args->gid;
+ virDomainDefPtr vmDef = args->vmDef;
+ char *path;
+
+ if (virSetUIDGID(uid, gid, NULL, 0) < 0) {
+ virReportSystemError(errno, "%s",
+ _("setuid or setgid failed"));
+ _exit(-1);
+ }
+
+ for (i = 0; i < vmDef->nfss; i++) {
+ path = vmDef->fss[i]->src;
+ if (access(path, R_OK) || access(path, W_OK) || virFileIsExecutable(path)) {
+ VIR_DEBUG("Src dir '%s' does not belong to uid/gid: %d/%d",
+ vmDef->fss[i]->src, uid, gid);
+ _exit(-1);
+ }
+ }
+
+ _exit(0);
+}
+
+/*
+ * Helper function for helping check
+ * whether we have enough privilege
+ * to operate the source dir when userns enabled
+ * @vmDef: pointer to vm definition structure
+ * Returns 0 on success or -1 in case of error
+ */
+static int
+lxcContainerCheckDirPermission(virDomainDefPtr vmDef)
+{
+ uid_t uid;
+ gid_t gid;
+ int cpid = 0;
+ int status;
+ char *childStack;
+ char *stack;
+ int flags = SIGCHLD;
+
+ uid = vmDef->idmap.uidmap[0].target;
+ gid = vmDef->idmap.gidmap[0].target;
+
+ lxc_userns_DirPermCheck_argv_t args = {
+ .uid = uid,
+ .gid = gid,
+ .vmDef = vmDef
+ };
+
+ if (VIR_ALLOC_N(stack, getpagesize() * 4) < 0)
+ return -1;
+
+ childStack = stack + (getpagesize() * 4);
+ cpid = clone(lxcContainerCheckDirPermissionChild, childStack, flags, &args);
+ VIR_FREE(stack);
+ if (cpid < 0) {
+ virReportSystemError(errno, "%s",
+ _("Unable to clone to check permission of directory"));
+ return -1;
+ } else if (virProcessWait(cpid, &status) < 0) {
+ return -1;
+ }
+
+ if (WEXITSTATUS(status) != 0) {
+ virReportSystemError(errno, "%s",
+ _("Check the permission of source dir provided for container"));
+ return -1;
+ }
+
+ return 0;
+}
+
/**
* lxcContainerStart:
* @def: pointer to virtual machine structure
@@ -1880,6 +1965,9 @@ int lxcContainerStart(virDomainDefPtr def,
if (userns_supported()) {
VIR_DEBUG("Enable user namespace");
cflags |= CLONE_NEWUSER;
+ if (lxcContainerCheckDirPermission(def) < 0) {
+ return -1;
+ }
} else {
virReportSystemError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("Kernel doesn't support user namespace"));
--
1.8.2.1
2
4
Re: [libvirt] [Qemu-devel] [RFC PATCH] spapr-vty: workaround "reg" property for old kernels
by Anthony Liguori 16 Oct '13
by Anthony Liguori 16 Oct '13
16 Oct '13
On Tue, Oct 15, 2013 at 3:47 PM, Alexey Kardashevskiy <aik(a)ozlabs.ru> wrote:
> On 10/16/2013 02:03 AM, Alexander Graf wrote:
>> On 10/15/2013 10:50 AM, Alexey Kardashevskiy wrote:
>>> Old kernels (< 3.1) handle hvcX devices different in different parts.
>>> Sometime the kernel assumes that the hvc device numbers start from zero
>>> and if there is just one hvc, then it is hvc0.
>>>
>>> However kernel's add_preferred_console() uses the very last byte of
>>> the VTY's "reg" property as an hvc number so it might end up with something
>>> different than hvc.
>>>
>>> The problem appears on SLES11SP3 and RHEL6. If to run QEMU without
>>> -nodefaults, then the default VTY is created first on a VIO bus and gets
>>> reg==0x71000000 so it will be hvc0 and everything will be fine.
>>> If to run QEMU with:
>>> -nodefaults \
>>> -chardev "socket,id=char1,host=localhost,port=8001,server,telnet,mux=on" \
>>> -device "spapr-vty,chardev=char1" \
>>> -mon "chardev=char1,mode=readline,id=mon1" \
>>>
>>> then the exactly the same config is expected but in this case spapr-vty
>>> gets reg==0x71000001 and therefore it becomes hvc1 and lots of debug
>>> output is missing. SLES11SP3 does not even boot as /dev/console is
>>> redirected to /dev/hvc0 which is dead.
>>>
>>> The issue can be solved by manual selection of VTY's "reg" property to
>>> have last byte equal to zero.
>>>
>>> The alternative would be to use separate "reg" property counter for
>>> automatic "reg" property generation and this is what the patch does.
>>>
>>> Signed-off-by: Alexey Kardashevskiy<aik(a)ozlabs.ru>
>>> ---
>>>
>>> Since libvirt uses "-nodefault" a lot and in this case "spapr-nvram" gets
>>> created first and gets reg=0x71000000, we cannot just ignore this. Also,
>>> it does not seem an option to require libvirt users to specify spapr-vty
>>> "reg" property every time.
>>>
>>> Can anyone think of a simpler solutionu? Thanks.
>>>
>>>
>>> ---
>>> hw/ppc/spapr_vio.c | 7 ++++++-
>>> include/hw/ppc/spapr_vio.h | 1 +
>>> 2 files changed, 7 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
>>> index a6a0a51..2d56950 100644
>>> --- a/hw/ppc/spapr_vio.c
>>> +++ b/hw/ppc/spapr_vio.c
>>> @@ -438,7 +438,11 @@ static int spapr_vio_busdev_init(DeviceState *qdev)
>>> VIOsPAPRBus *bus = DO_UPCAST(VIOsPAPRBus, bus,
>>> dev->qdev.parent_bus);
>>>
>>> do {
>>> - dev->reg = bus->next_reg++;
>>> + if (!object_dynamic_cast(OBJECT(qdev), "spapr-vty")) {
>>> + dev->reg = bus->next_reg++;
>>> + } else {
>>> + dev->reg = bus->next_vty_reg++;
>>> + }
>>> } while (reg_conflict(dev));
>>> }
>>>
>>> @@ -501,6 +505,7 @@ VIOsPAPRBus *spapr_vio_bus_init(void)
>>> qbus = qbus_create(TYPE_SPAPR_VIO_BUS, dev, "spapr-vio");
>>> bus = DO_UPCAST(VIOsPAPRBus, bus, qbus);
>>> bus->next_reg = 0x71000000;
>>> + bus->next_vty_reg = 0x71000100;
>>
>> This breaks as soon as you pass in more than 0x100 devices that are non-vty
>> into the guest, no?
>
> Will we ever have this much? Ah, anyway, this code already checks if the
> address is taken and fails if it is. And there is still a possibility to
> assign addresses manually.
>
>> The reg property really describes the virtual slot a device is in.
>
> We use 0x71000000. I saw xmls from libvirt where VTY's reg is 0x30000000.
> Whether it is a slot or not, QEMU/SLOF/Kernel does not seem to care about
> absolute value :)
>
>> Couldn't
>> we do that allocation explicitly and push it from libvirt, just like we do
>> it with the slots for PCI?
Yes, this is the only solution. We make no promises with respect to
argument ordering. libvirt needs to explicitly specify reg values to
create a stable device tree (just like it does with PCI).
Regards,
Anthony Liguori
>
> That is the other possibility, yes. But in this case "-nodefaults" must not
> create spapr-nvram automatically and if we do that, we'll break existing
> setups.
>
>
>>
>>
>> Alex
>>
>>
>>>
>>> /* hcall-vio */
>>> spapr_register_hypercall(H_VIO_SIGNAL, h_vio_signal);
>>> diff --git a/include/hw/ppc/spapr_vio.h b/include/hw/ppc/spapr_vio.h
>>> index d8b3b03..3a92d9e 100644
>>> --- a/include/hw/ppc/spapr_vio.h
>>> +++ b/include/hw/ppc/spapr_vio.h
>>> @@ -73,6 +73,7 @@ struct VIOsPAPRDevice {
>>> struct VIOsPAPRBus {
>>> BusState bus;
>>> uint32_t next_reg;
>>> + uint32_t next_vty_reg;
>>> int (*init)(VIOsPAPRDevice *dev);
>>> int (*devnode)(VIOsPAPRDevice *dev, void *fdt, int node_off);
>>> };
>>
>
>
> --
> Alexey
>
1
0
This should resolve:
https://bugzilla.redhat.com/show_bug.cgi?id=924672
For BZ 924672 the problem stems from the fact that thin pool logical
volume devices show up in /sbin/lvs output just like normal logical
volumes do. Libvirt incorrectly assumes they are just normal logical
volumes and that they will have a corresponding /dev/vgname/lvname
device that has been created by udev and tries to use this device.
To illustrate here is an example of the /dev/vgname/ directory and
the lvs output for a normal lv, thin lv, and thin pool:
LV VG Attr LSize Pool Origin Data% Move Log Copy% Convert
lv vgguests -wi-a---- 1.00g
pool vgguests twi-a-tz- 11.00g 0.00
thinlv vgguests Vwi-a-tz- 1.00g pool 0.00
total 0
lrwxrwxrwx. 1 root root 7 Oct 8 19:35 lv -> ../dm-7
lrwxrwxrwx. 1 root root 7 Oct 8 19:37 thinlv -> ../dm-6
This patch modifies virStorageBackendLogicalMakeVol() to ignore thin pool
devices.
---
src/storage/storage_backend_logical.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/src/storage/storage_backend_logical.c b/src/storage/storage_backend_logical.c
index a1a37a1..81ee4a4 100644
--- a/src/storage/storage_backend_logical.c
+++ b/src/storage/storage_backend_logical.c
@@ -85,6 +85,14 @@ virStorageBackendLogicalMakeVol(virStoragePoolObjPtr pool,
if (attrs[4] != 'a')
return 0;
+ /*
+ * Skip thin pools(t). These show up in normal lvs output
+ * but do not have a corresponding /dev/$vg/$lv device that
+ * is created by udev. This breaks assumptions in later code.
+ */
+ if (attrs[0] == 't')
+ return 0;
+
/* See if we're only looking for a specific volume */
if (data != NULL) {
vol = data;
--
1.8.3.1
2
2
This patch adds two new classes, filterref and filterref-parameter.
Network interfaces can now have an associated filter reference with any
number of filterref parameters. Also added filter= option to
virt-sandbox tool.
---
libvirt-sandbox/Makefile.am | 4 +
.../libvirt-sandbox-builder-container.c | 37 +++-
libvirt-sandbox/libvirt-sandbox-builder-machine.c | 36 ++++
...rt-sandbox-config-network-filterref-parameter.c | 205 ++++++++++++++++++++
...rt-sandbox-config-network-filterref-parameter.h | 75 ++++++++
.../libvirt-sandbox-config-network-filterref.c | 209 +++++++++++++++++++++
.../libvirt-sandbox-config-network-filterref.h | 75 ++++++++
libvirt-sandbox/libvirt-sandbox-config-network.c | 33 ++++
libvirt-sandbox/libvirt-sandbox-config-network.h | 4 +
libvirt-sandbox/libvirt-sandbox-config.c | 39 ++++
libvirt-sandbox/libvirt-sandbox.h | 2 +
libvirt-sandbox/libvirt-sandbox.sym | 14 ++
12 files changed, 732 insertions(+), 1 deletion(-)
create mode 100644 libvirt-sandbox/libvirt-sandbox-config-network-filterref-parameter.c
create mode 100644 libvirt-sandbox/libvirt-sandbox-config-network-filterref-parameter.h
create mode 100644 libvirt-sandbox/libvirt-sandbox-config-network-filterref.c
create mode 100644 libvirt-sandbox/libvirt-sandbox-config-network-filterref.h
diff --git a/libvirt-sandbox/Makefile.am b/libvirt-sandbox/Makefile.am
index 0882490..4de8766 100644
--- a/libvirt-sandbox/Makefile.am
+++ b/libvirt-sandbox/Makefile.am
@@ -57,6 +57,8 @@ SANDBOX_HEADER_FILES = \
libvirt-sandbox-config.h \
libvirt-sandbox-config-network.h \
libvirt-sandbox-config-network-address.h \
+ libvirt-sandbox-config-network-filterref.h \
+ libvirt-sandbox-config-network-filterref-parameter.h \
libvirt-sandbox-config-network-route.h \
libvirt-sandbox-config-mount.h \
libvirt-sandbox-config-mount-file.h \
@@ -85,6 +87,8 @@ SANDBOX_SOURCE_FILES = \
libvirt-sandbox-config.c \
libvirt-sandbox-config-network.c \
libvirt-sandbox-config-network-address.c \
+ libvirt-sandbox-config-network-filterref.c \
+ libvirt-sandbox-config-network-filterref-parameter.c \
libvirt-sandbox-config-network-route.c \
libvirt-sandbox-config-mount.c \
libvirt-sandbox-config-mount-file.c \
diff --git a/libvirt-sandbox/libvirt-sandbox-builder-container.c b/libvirt-sandbox/libvirt-sandbox-builder-container.c
index 43ee5ef..193b777 100644
--- a/libvirt-sandbox/libvirt-sandbox-builder-container.c
+++ b/libvirt-sandbox/libvirt-sandbox-builder-container.c
@@ -319,11 +319,12 @@ static gboolean gvir_sandbox_builder_container_construct_devices(GVirSandboxBuil
g_list_foreach(mounts, (GFunc)g_object_unref, NULL);
g_list_free(mounts);
-
tmp = networks = gvir_sandbox_config_get_networks(config);
while (tmp) {
const gchar *source, *mac;
GVirSandboxConfigNetwork *network = GVIR_SANDBOX_CONFIG_NETWORK(tmp->data);
+ GVirSandboxConfigNetworkFilterref *filterref;
+ GVirConfigDomainInterfaceFilterref *glib_fref;
iface = gvir_config_domain_interface_network_new();
source = gvir_sandbox_config_network_get_source(network);
@@ -339,6 +340,40 @@ static gboolean gvir_sandbox_builder_container_construct_devices(GVirSandboxBuil
gvir_config_domain_add_device(domain,
GVIR_CONFIG_DOMAIN_DEVICE(iface));
+
+ filterref = gvir_sandbox_config_network_get_filterref(network);
+ if (filterref) {
+ GList *param_iter, *parameters;
+ const gchar *fref_name = gvir_sandbox_config_network_filterref_get_filter(filterref);
+ glib_fref = gvir_config_domain_interface_filterref_new();
+ gvir_config_domain_interface_filterref_set_filter(glib_fref, fref_name);
+ param_iter = parameters = gvir_sandbox_config_network_filterref_get_parameters(filterref);
+ while (param_iter) {
+ const gchar *name;
+ const gchar *value;
+ GVirSandboxConfigNetworkFilterrefParameter *param = GVIR_SANDBOX_CONFIG_NETWORK_FILTERREF_PARAMETER(param_iter->data);
+ GVirConfigDomainInterfaceFilterrefParameter *glib_param;
+
+ name = gvir_sandbox_config_network_filterref_parameter_get_name(param);
+ value = gvir_sandbox_config_network_filterref_parameter_get_value(param);
+
+ glib_param = gvir_config_domain_interface_filterref_parameter_new();
+ gvir_config_domain_interface_filterref_parameter_set_name(glib_param, name);
+ gvir_config_domain_interface_filterref_parameter_set_value(glib_param, value);
+
+ gvir_config_domain_interface_filterref_add_parameter(glib_fref, glib_param);
+ g_object_unref(glib_param);
+
+ param_iter = param_iter->next;
+ }
+
+ g_list_foreach(parameters, (GFunc)g_object_unref, NULL);
+ g_list_free(parameters);
+
+ gvir_config_domain_interface_set_filterref(GVIR_CONFIG_DOMAIN_INTERFACE(iface), glib_fref);
+ g_object_unref(glib_fref);
+ }
+
g_object_unref(iface);
tmp = tmp->next;
diff --git a/libvirt-sandbox/libvirt-sandbox-builder-machine.c b/libvirt-sandbox/libvirt-sandbox-builder-machine.c
index a8c5d8c..072bbbe 100644
--- a/libvirt-sandbox/libvirt-sandbox-builder-machine.c
+++ b/libvirt-sandbox/libvirt-sandbox-builder-machine.c
@@ -577,6 +577,8 @@ static gboolean gvir_sandbox_builder_machine_construct_devices(GVirSandboxBuilde
while (tmp) {
const gchar *source, *mac;
GVirSandboxConfigNetwork *network = GVIR_SANDBOX_CONFIG_NETWORK(tmp->data);
+ GVirSandboxConfigNetworkFilterref *filterref;
+ GVirConfigDomainInterfaceFilterref *glib_fref;
source = gvir_sandbox_config_network_get_source(network);
if (source) {
@@ -596,6 +598,40 @@ static gboolean gvir_sandbox_builder_machine_construct_devices(GVirSandboxBuilde
gvir_config_domain_add_device(domain,
GVIR_CONFIG_DOMAIN_DEVICE(iface));
+
+ filterref = gvir_sandbox_config_network_get_filterref(network);
+ if (filterref) {
+ GList *param_iter, *parameters;
+ const gchar *fref_name = gvir_sandbox_config_network_filterref_get_filter(filterref);
+ glib_fref = gvir_config_domain_interface_filterref_new();
+ gvir_config_domain_interface_filterref_set_filter(glib_fref, fref_name);
+ param_iter = parameters = gvir_sandbox_config_network_filterref_get_parameters(filterref);
+ while (param_iter) {
+ const gchar *name;
+ const gchar *value;
+ GVirSandboxConfigNetworkFilterrefParameter *param = GVIR_SANDBOX_CONFIG_NETWORK_FILTERREF_PARAMETER(param_iter->data);
+ GVirConfigDomainInterfaceFilterrefParameter *glib_param;
+
+ name = gvir_sandbox_config_network_filterref_parameter_get_name(param);
+ value = gvir_sandbox_config_network_filterref_parameter_get_value(param);
+
+ glib_param = gvir_config_domain_interface_filterref_parameter_new();
+ gvir_config_domain_interface_filterref_parameter_set_name(glib_param, name);
+ gvir_config_domain_interface_filterref_parameter_set_value(glib_param, value);
+
+ gvir_config_domain_interface_filterref_add_parameter(glib_fref, glib_param);
+ g_object_unref(glib_param);
+
+ param_iter = param_iter->next;
+ }
+
+ g_list_foreach(parameters, (GFunc)g_object_unref, NULL);
+ g_list_free(parameters);
+
+ gvir_config_domain_interface_set_filterref(iface, glib_fref);
+ g_object_unref(glib_fref);
+ }
+
g_object_unref(iface);
tmp = tmp->next;
diff --git a/libvirt-sandbox/libvirt-sandbox-config-network-filterref-parameter.c b/libvirt-sandbox/libvirt-sandbox-config-network-filterref-parameter.c
new file mode 100644
index 0000000..c1ed941
--- /dev/null
+++ b/libvirt-sandbox/libvirt-sandbox-config-network-filterref-parameter.c
@@ -0,0 +1,205 @@
+/*
+ * libvirt-sandbox-config-network-filterref-parameter.c: libvirt sandbox configuration
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author: Ian Main <imain(a)redhat.com>
+ */
+
+#include <config.h>
+#include <string.h>
+
+#include "libvirt-sandbox/libvirt-sandbox.h"
+
+/**
+ * SECTION: libvirt-sandbox-config-network-filterref-parameter
+ * @short_description: Set parameters for a filter reference.
+ * @include: libvirt-sandbox/libvirt-sandbox.h
+ *
+ * Provides an object to store filter parameter name and value.
+ *
+ * The GVirSandboxConfigNetworkFilterrefParameter object stores a
+ * name and value required to set a single parameter of a filter reference.
+ */
+
+#define GVIR_SANDBOX_CONFIG_NETWORK_FILTERREF_PARAMETER_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE((obj), GVIR_SANDBOX_TYPE_CONFIG_NETWORK_FILTERREF_PARAMETER, GVirSandboxConfigNetworkFilterrefParameterPrivate))
+
+struct _GVirSandboxConfigNetworkFilterrefParameterPrivate
+{
+ gchar *name;
+ gchar *value;
+};
+
+G_DEFINE_TYPE(GVirSandboxConfigNetworkFilterrefParameter, gvir_sandbox_config_network_filterref_parameter, G_TYPE_OBJECT);
+
+
+enum {
+ PROP_0,
+ PROP_NAME,
+ PROP_VALUE,
+};
+
+enum {
+ LAST_SIGNAL
+};
+
+//static gint signals[LAST_SIGNAL];
+
+
+static void gvir_sandbox_config_network_filterref_parameter_get_property(GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GVirSandboxConfigNetworkFilterrefParameter *config = GVIR_SANDBOX_CONFIG_NETWORK_FILTERREF_PARAMETER(object);
+ GVirSandboxConfigNetworkFilterrefParameterPrivate *priv = config->priv;
+
+ switch (prop_id) {
+ case PROP_NAME:
+ g_value_set_string(value, priv->name);
+ break;
+
+ case PROP_VALUE:
+ g_value_set_string(value, priv->value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ }
+}
+
+
+static void gvir_sandbox_config_network_filterref_parameter_set_property(GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GVirSandboxConfigNetworkFilterrefParameter *config = GVIR_SANDBOX_CONFIG_NETWORK_FILTERREF_PARAMETER(object);
+ GVirSandboxConfigNetworkFilterrefParameterPrivate *priv = config->priv;
+
+ switch (prop_id) {
+ case PROP_NAME:
+ g_free(priv->name);
+ priv->name = g_value_dup_string(value);
+ break;
+
+ case PROP_VALUE:
+ g_free(priv->value);
+ priv->value = g_value_dup_string(value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ }
+}
+
+
+static void gvir_sandbox_config_network_filterref_parameter_finalize(GObject *object)
+{
+ GVirSandboxConfigNetworkFilterrefParameter *config = GVIR_SANDBOX_CONFIG_NETWORK_FILTERREF_PARAMETER(object);
+ GVirSandboxConfigNetworkFilterrefParameterPrivate *priv = config->priv;
+
+ g_free(priv->name);
+ g_free(priv->value);
+
+ G_OBJECT_CLASS(gvir_sandbox_config_network_filterref_parameter_parent_class)->finalize(object);
+}
+
+
+static void gvir_sandbox_config_network_filterref_parameter_class_init(GVirSandboxConfigNetworkFilterrefParameterClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS(klass);
+
+ object_class->finalize = gvir_sandbox_config_network_filterref_parameter_finalize;
+ object_class->get_property = gvir_sandbox_config_network_filterref_parameter_get_property;
+ object_class->set_property = gvir_sandbox_config_network_filterref_parameter_set_property;
+
+ g_object_class_install_property(object_class,
+ PROP_NAME,
+ g_param_spec_string("name",
+ "Name",
+ "Name of parameter",
+ NULL,
+ G_PARAM_READABLE |
+ G_PARAM_WRITABLE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ g_object_class_install_property(object_class,
+ PROP_VALUE,
+ g_param_spec_string("value",
+ "Value",
+ "Value of parameter",
+ NULL,
+ G_PARAM_READABLE |
+ G_PARAM_WRITABLE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ g_type_class_add_private(klass, sizeof(GVirSandboxConfigNetworkFilterrefParameterPrivate));
+}
+
+
+static void gvir_sandbox_config_network_filterref_parameter_init(GVirSandboxConfigNetworkFilterrefParameter *param)
+{
+ param->priv = GVIR_SANDBOX_CONFIG_NETWORK_FILTERREF_PARAMETER_GET_PRIVATE(param);
+}
+
+
+/**
+ * gvir_sandbox_config_network_filterref_parameter_new:
+ *
+ * Create a new network config with DHCP enabled
+ *
+ * Returns: (transfer full): a new sandbox network object
+ */
+GVirSandboxConfigNetworkFilterrefParameter *gvir_sandbox_config_network_filterref_parameter_new(void)
+{
+ return GVIR_SANDBOX_CONFIG_NETWORK_FILTERREF_PARAMETER(g_object_new(GVIR_SANDBOX_TYPE_CONFIG_NETWORK_FILTERREF_PARAMETER,
+ NULL));
+}
+
+void gvir_sandbox_config_network_filterref_parameter_set_name(GVirSandboxConfigNetworkFilterrefParameter *param,
+ const gchar *name)
+{
+ GVirSandboxConfigNetworkFilterrefParameterPrivate *priv = param->priv;
+ g_free(priv->name);
+ priv->name = g_strdup(name);
+}
+
+const gchar *gvir_sandbox_config_network_filterref_parameter_get_name(GVirSandboxConfigNetworkFilterrefParameter *param)
+{
+ GVirSandboxConfigNetworkFilterrefParameterPrivate *priv = param->priv;
+ return priv->name;
+}
+
+void gvir_sandbox_config_network_filterref_parameter_set_value(GVirSandboxConfigNetworkFilterrefParameter *param,
+ const gchar *value)
+{
+ GVirSandboxConfigNetworkFilterrefParameterPrivate *priv = param->priv;
+ g_free(priv->value);
+ priv->value = g_strdup(value);
+}
+
+const gchar *gvir_sandbox_config_network_filterref_parameter_get_value(GVirSandboxConfigNetworkFilterrefParameter *param)
+{
+ GVirSandboxConfigNetworkFilterrefParameterPrivate *priv = param->priv;
+ return priv->value;
+}
diff --git a/libvirt-sandbox/libvirt-sandbox-config-network-filterref-parameter.h b/libvirt-sandbox/libvirt-sandbox-config-network-filterref-parameter.h
new file mode 100644
index 0000000..f40895f
--- /dev/null
+++ b/libvirt-sandbox/libvirt-sandbox-config-network-filterref-parameter.h
@@ -0,0 +1,75 @@
+/*
+ * libvirt-sandbox-config-network-filterref-parameter.h: libvirt sandbox configuration
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author: Ian Main <imain(a)redhat.com>
+ */
+
+#if !defined(__LIBVIRT_SANDBOX_H__) && !defined(LIBVIRT_SANDBOX_BUILD)
+#error "Only <libvirt-sandbox/libvirt-sandbox.h> can be included directly."
+#endif
+
+#ifndef __LIBVIRT_SANDBOX_CONFIG_NETWORK_FILTERREF_PARAMETER_H__
+#define __LIBVIRT_SANDBOX_CONFIG_NETWORK_FILTERREF_PARAMETER_H__
+
+G_BEGIN_DECLS
+
+#define GVIR_SANDBOX_TYPE_CONFIG_NETWORK_FILTERREF_PARAMETER (gvir_sandbox_config_network_filterref_parameter_get_type ())
+#define GVIR_SANDBOX_CONFIG_NETWORK_FILTERREF_PARAMETER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GVIR_SANDBOX_TYPE_CONFIG_NETWORK_FILTERREF_PARAMETER, GVirSandboxConfigNetworkFilterrefParameter))
+#define GVIR_SANDBOX_CONFIG_NETWORK_FILTERREF_PARAMETER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GVIR_SANDBOX_TYPE_CONFIG_NETWORK_FILTERREF_PARAMETER, GVirSandboxConfigNetworkFilterrefParameterClass))
+#define GVIR_SANDBOX_IS_CONFIG_NETWORK_FILTERREF_PARAMETER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GVIR_SANDBOX_TYPE_CONFIG_NETWORK_FILTERREF_PARAMETER))
+#define GVIR_SANDBOX_IS_CONFIG_NETWORK_FILTERREF_PARAMETER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GVIR_SANDBOX_TYPE_CONFIG_NETWORK_FILTERREF_PARAMETER))
+#define GVIR_SANDBOX_CONFIG_NETWORK_FILTERREF_PARAMETER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GVIR_SANDBOX_TYPE_CONFIG_NETWORK_FILTERREF_PARAMETER, GVirSandboxConfigNetworkFilterrefParameterClass))
+
+#define GVIR_SANDBOX_TYPE_CONFIG_NETWORK_FILTERREF_PARAMETER_HANDLE (gvir_sandbox_config_network_filterref_parameter_handle_get_type ())
+
+typedef struct _GVirSandboxConfigNetworkFilterrefParameter GVirSandboxConfigNetworkFilterrefParameter;
+typedef struct _GVirSandboxConfigNetworkFilterrefParameterPrivate GVirSandboxConfigNetworkFilterrefParameterPrivate;
+typedef struct _GVirSandboxConfigNetworkFilterrefParameterClass GVirSandboxConfigNetworkFilterrefParameterClass;
+
+struct _GVirSandboxConfigNetworkFilterrefParameter
+{
+ GObject parent;
+
+ GVirSandboxConfigNetworkFilterrefParameterPrivate *priv;
+
+ /* Do not add fields to this struct */
+};
+
+struct _GVirSandboxConfigNetworkFilterrefParameterClass
+{
+ GObjectClass parent_class;
+
+ gpointer padding[LIBVIRT_SANDBOX_CLASS_PADDING];
+};
+
+GType gvir_sandbox_config_network_filterref_parameter_get_type(void);
+
+GVirSandboxConfigNetworkFilterrefParameter *gvir_sandbox_config_network_filterref_parameter_new(void);
+
+void gvir_sandbox_config_network_filterref_parameter_set_name(GVirSandboxConfigNetworkFilterrefParameter *param,
+ const gchar *name);
+const gchar *gvir_sandbox_config_network_filterref_parameter_get_name(GVirSandboxConfigNetworkFilterrefParameter *param);
+
+void gvir_sandbox_config_network_filterref_parameter_set_value(GVirSandboxConfigNetworkFilterrefParameter *param,
+ const gchar *value);
+const gchar *gvir_sandbox_config_network_filterref_parameter_get_value(GVirSandboxConfigNetworkFilterrefParameter *param);
+
+G_END_DECLS
+
+#endif /* __LIBVIRT_SANDBOX_CONFIG_NETWORK_FILTERREF_PARAMETER_H__ */
diff --git a/libvirt-sandbox/libvirt-sandbox-config-network-filterref.c b/libvirt-sandbox/libvirt-sandbox-config-network-filterref.c
new file mode 100644
index 0000000..ee8ff89
--- /dev/null
+++ b/libvirt-sandbox/libvirt-sandbox-config-network-filterref.c
@@ -0,0 +1,209 @@
+/*
+ * libvirt-sandbox-config-mount.c: libvirt sandbox configuration
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author: Ian Main <imain(a)redhat.com>
+ */
+
+#include <config.h>
+#include <string.h>
+
+#include "libvirt-sandbox/libvirt-sandbox.h"
+
+/**
+ * SECTION: libvirt-sandbox-config-network-filterref
+ * @short_description: Add a network filter to a network interface.
+ * @include: libvirt-sandbox/libvirt-sandbox.h
+ * @see_aloso: #GVirSandboxConfig
+ *
+ * Provides an object to store the name of the filter reference.
+ *
+ * The GVirSandboxConfigNetworkFilterref object stores the name of the filter
+ * references associated with a network interface.
+ */
+
+#define GVIR_SANDBOX_CONFIG_NETWORK_FILTERREF_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE((obj), GVIR_SANDBOX_TYPE_CONFIG_NETWORK_FILTERREF, GVirSandboxConfigNetworkFilterrefPrivate))
+
+struct _GVirSandboxConfigNetworkFilterrefPrivate
+{
+ gchar *filter;
+ GList *parameters;
+};
+
+G_DEFINE_TYPE(GVirSandboxConfigNetworkFilterref, gvir_sandbox_config_network_filterref, G_TYPE_OBJECT);
+
+
+enum {
+ PROP_0,
+ PROP_FILTER
+};
+
+enum {
+ LAST_SIGNAL
+};
+
+//static gint signals[LAST_SIGNAL];
+
+static void gvir_sandbox_config_network_filterref_get_property(GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GVirSandboxConfigNetworkFilterref *config = GVIR_SANDBOX_CONFIG_NETWORK_FILTERREF(object);
+ GVirSandboxConfigNetworkFilterrefPrivate *priv = config->priv;
+
+ switch (prop_id) {
+ case PROP_FILTER:
+ g_value_set_string(value, priv->filter);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ }
+}
+
+
+static void gvir_sandbox_config_network_filterref_set_property(GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GVirSandboxConfigNetworkFilterref *config = GVIR_SANDBOX_CONFIG_NETWORK_FILTERREF(object);
+ GVirSandboxConfigNetworkFilterrefPrivate *priv = config->priv;
+
+ switch (prop_id) {
+ case PROP_FILTER:
+ g_free(priv->filter);
+ priv->filter = g_value_dup_string(value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ }
+}
+
+
+
+static void gvir_sandbox_config_network_filterref_finalize(GObject *object)
+{
+ GVirSandboxConfigNetworkFilterref *config = GVIR_SANDBOX_CONFIG_NETWORK_FILTERREF(object);
+ GVirSandboxConfigNetworkFilterrefPrivate *priv = config->priv;
+
+ g_free(priv->filter);
+ g_list_foreach(priv->parameters, (GFunc)g_object_unref, NULL);
+
+ G_OBJECT_CLASS(gvir_sandbox_config_network_filterref_parent_class)->finalize(object);
+}
+
+
+static void gvir_sandbox_config_network_filterref_class_init(GVirSandboxConfigNetworkFilterrefClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS(klass);
+
+ object_class->finalize = gvir_sandbox_config_network_filterref_finalize;
+ object_class->get_property = gvir_sandbox_config_network_filterref_get_property;
+ object_class->set_property = gvir_sandbox_config_network_filterref_set_property;
+
+ g_object_class_install_property(object_class,
+ PROP_FILTER,
+ g_param_spec_string("filter",
+ "Filter name",
+ "The filter reference name",
+ NULL,
+ G_PARAM_READABLE |
+ G_PARAM_WRITABLE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ g_type_class_add_private(klass, sizeof(GVirSandboxConfigNetworkFilterrefPrivate));
+}
+
+/**
+ * gvir_sandbox_config_network_filterref_new:
+ *
+ * Create a new network filterref config.
+ *
+ * Returns: (transfer full): a new sandbox network_filterref object
+ */
+GVirSandboxConfigNetworkFilterref *gvir_sandbox_config_network_filterref_new(void)
+{
+ return GVIR_SANDBOX_CONFIG_NETWORK_FILTERREF(g_object_new(GVIR_SANDBOX_TYPE_CONFIG_NETWORK_FILTERREF,
+ NULL));
+}
+
+
+static void gvir_sandbox_config_network_filterref_init(GVirSandboxConfigNetworkFilterref *config)
+{
+ config->priv = GVIR_SANDBOX_CONFIG_NETWORK_FILTERREF_GET_PRIVATE(config);
+}
+
+
+/**
+ * gvir_sandbox_config_network_filterref_get_filter:
+ * @config: (transfer none): the network filter reference name
+ *
+ * Retrieves the network filter reference name.
+ *
+ * Returns: (transfer none): the network filter reference name.
+ */
+const gchar *gvir_sandbox_config_network_filterref_get_filter(GVirSandboxConfigNetworkFilterref *config)
+{
+ GVirSandboxConfigNetworkFilterrefPrivate *priv = config->priv;
+ return priv->filter;
+}
+
+void gvir_sandbox_config_network_filterref_set_filter(GVirSandboxConfigNetworkFilterref *config,
+ const gchar *name)
+{
+ GVirSandboxConfigNetworkFilterrefPrivate *priv = config->priv;
+ g_free(priv->filter);
+ priv->filter = g_strdup(name);
+}
+
+/**
+ * gvir_sandbox_config_network_filterref_add_parameter:
+ * @filter: (transfer none): the network filter reference.
+ * @param: (transfer none): the filter parameter
+ *
+ * Add a parameter to a network filter reference.
+ */
+void gvir_sandbox_config_network_filterref_add_parameter(GVirSandboxConfigNetworkFilterref *filter,
+ GVirSandboxConfigNetworkFilterrefParameter *param)
+{
+ GVirSandboxConfigNetworkFilterrefPrivate *priv = filter->priv;
+ priv->parameters = g_list_append(priv->parameters, g_object_ref(param));
+}
+
+
+/**
+ * gvir_sandbox_config_network_filterref_get_parameters:
+ * @filter: (transfer none): the filter reference configuration
+ *
+ * Retrieve the list of parameters associated with a network filter reference
+ *
+ * Returns: (transfer full)(element-type GVirSandboxConfigNetworkFilterrefParameter): the parameter list
+ */
+GList *gvir_sandbox_config_network_filterref_get_parameters(GVirSandboxConfigNetworkFilterref *filter)
+{
+ GVirSandboxConfigNetworkFilterrefPrivate *priv = filter->priv;
+ g_list_foreach(priv->parameters, (GFunc)g_object_ref, NULL);
+ return g_list_copy(priv->parameters);
+}
diff --git a/libvirt-sandbox/libvirt-sandbox-config-network-filterref.h b/libvirt-sandbox/libvirt-sandbox-config-network-filterref.h
new file mode 100644
index 0000000..5d264a5
--- /dev/null
+++ b/libvirt-sandbox/libvirt-sandbox-config-network-filterref.h
@@ -0,0 +1,75 @@
+/*
+ * libvirt-sandbox-config-mount.h: libvirt sandbox configuration
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author: Ian Main <imain(a)redhat.com>
+ */
+
+#if !defined(__LIBVIRT_SANDBOX_H__) && !defined(LIBVIRT_SANDBOX_BUILD)
+#error "Only <libvirt-sandbox/libvirt-sandbox.h> can be included directly."
+#endif
+
+#ifndef __LIBVIRT_SANDBOX_CONFIG_NETWORK_FILTERREF_H__
+#define __LIBVIRT_SANDBOX_CONFIG_NETWORK_FILTERREF_H__
+
+G_BEGIN_DECLS
+
+#define GVIR_SANDBOX_TYPE_CONFIG_NETWORK_FILTERREF (gvir_sandbox_config_network_filterref_get_type ())
+#define GVIR_SANDBOX_CONFIG_NETWORK_FILTERREF(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GVIR_SANDBOX_TYPE_CONFIG_NETWORK_FILTERREF, GVirSandboxConfigNetworkFilterref))
+#define GVIR_SANDBOX_CONFIG_NETWORK_FILTERREF_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GVIR_SANDBOX_TYPE_CONFIG_NETWORK_FILTERREF, GVirSandboxConfigNetworkFilterrefClass))
+#define GVIR_SANDBOX_IS_CONFIG_NETWORK_FILTERREF(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GVIR_SANDBOX_TYPE_CONFIG_NETWORK_FILTERREF))
+#define GVIR_SANDBOX_IS_CONFIG_NETWORK_FILTERREF_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GVIR_SANDBOX_TYPE_CONFIG_NETWORK_FILTERREF))
+#define GVIR_SANDBOX_CONFIG_NETWORK_FILTERREF_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GVIR_SANDBOX_TYPE_CONFIG_NETWORK_FILTERREF, GVirSandboxConfigNetworkFilterrefClass))
+
+#define GVIR_SANDBOX_TYPE_CONFIG_NETWORK_FILTERREF_HANDLE (gvir_sandbox_config_network_filterref_handle_get_type ())
+
+typedef struct _GVirSandboxConfigNetworkFilterref GVirSandboxConfigNetworkFilterref;
+typedef struct _GVirSandboxConfigNetworkFilterrefPrivate GVirSandboxConfigNetworkFilterrefPrivate;
+typedef struct _GVirSandboxConfigNetworkFilterrefClass GVirSandboxConfigNetworkFilterrefClass;
+
+struct _GVirSandboxConfigNetworkFilterref
+{
+ GObject parent;
+
+ GVirSandboxConfigNetworkFilterrefPrivate *priv;
+
+ /* Do not add fields to this struct */
+};
+
+struct _GVirSandboxConfigNetworkFilterrefClass
+{
+ GObjectClass parent_class;
+
+ gpointer padding[LIBVIRT_SANDBOX_CLASS_PADDING];
+};
+
+GType gvir_sandbox_config_network_filterref_get_type(void);
+
+GVirSandboxConfigNetworkFilterref *gvir_sandbox_config_network_filterref_new(void);
+
+const gchar *gvir_sandbox_config_network_filterref_get_filter(GVirSandboxConfigNetworkFilterref *config);
+void gvir_sandbox_config_network_filterref_set_filter(GVirSandboxConfigNetworkFilterref *filter, const gchar *name);
+
+void gvir_sandbox_config_network_filterref_add_parameter(GVirSandboxConfigNetworkFilterref *filter,
+ GVirSandboxConfigNetworkFilterrefParameter *param);
+GList *gvir_sandbox_config_network_filterref_get_parameters(GVirSandboxConfigNetworkFilterref *filter);
+
+
+G_END_DECLS
+
+#endif /* __LIBVIRT_SANDBOX_CONFIG_NETWORK_FILTERREF_H__ */
diff --git a/libvirt-sandbox/libvirt-sandbox-config-network.c b/libvirt-sandbox/libvirt-sandbox-config-network.c
index 7e7c015..555a360 100644
--- a/libvirt-sandbox/libvirt-sandbox-config-network.c
+++ b/libvirt-sandbox/libvirt-sandbox-config-network.c
@@ -47,6 +47,7 @@ struct _GVirSandboxConfigNetworkPrivate
gchar *mac;
GList *routes;
GList *addrs;
+ GVirSandboxConfigNetworkFilterref *filterref;
};
G_DEFINE_TYPE(GVirSandboxConfigNetwork, gvir_sandbox_config_network, G_TYPE_OBJECT);
@@ -285,6 +286,38 @@ GList *gvir_sandbox_config_network_get_addresses(GVirSandboxConfigNetwork *confi
}
/**
+ * gvir_sandbox_config_network_set_filterref:
+ * @config: (transfer none): the sandbox network configuration
+ * @ref: (transfer none): the network filterref
+ *
+ * Set a network filterref for the given network.
+ */
+void gvir_sandbox_config_network_set_filterref(GVirSandboxConfigNetwork *config,
+ GVirSandboxConfigNetworkFilterref *filterref)
+{
+ GVirSandboxConfigNetworkPrivate *priv = config->priv;
+ if (priv->filterref)
+ g_object_unref(priv->filterref);
+ priv->filterref = g_object_ref(filterref);
+}
+
+
+/**
+ * gvir_sandbox_config_network_get_filterref:
+ * @config: (transfer none): the sandbox network configuration
+ *
+ * Retrieve the associated filter reference.
+ *
+ * Returns: (transfer none): The associated filter reference.
+ */
+GVirSandboxConfigNetworkFilterref *gvir_sandbox_config_network_get_filterref(GVirSandboxConfigNetwork *config)
+{
+ GVirSandboxConfigNetworkPrivate *priv = config->priv;
+ return priv->filterref;
+}
+
+
+/**
* gvir_sandbox_config_network_add_route:
* @config: (transfer none): the sandbox network configuration
* @addr: (transfer none): the network route
diff --git a/libvirt-sandbox/libvirt-sandbox-config-network.h b/libvirt-sandbox/libvirt-sandbox-config-network.h
index d926fd1..4a52221 100644
--- a/libvirt-sandbox/libvirt-sandbox-config-network.h
+++ b/libvirt-sandbox/libvirt-sandbox-config-network.h
@@ -78,6 +78,10 @@ void gvir_sandbox_config_network_add_address(GVirSandboxConfigNetwork *config,
GVirSandboxConfigNetworkAddress *addr);
GList *gvir_sandbox_config_network_get_addresses(GVirSandboxConfigNetwork *config);
+void gvir_sandbox_config_network_set_filterref(GVirSandboxConfigNetwork *config,
+ GVirSandboxConfigNetworkFilterref *ref);
+GVirSandboxConfigNetworkFilterref *gvir_sandbox_config_network_get_filterref(GVirSandboxConfigNetwork *config);
+
void gvir_sandbox_config_network_add_route(GVirSandboxConfigNetwork *config,
GVirSandboxConfigNetworkRoute *addr);
GList *gvir_sandbox_config_network_get_routes(GVirSandboxConfigNetwork *config);
diff --git a/libvirt-sandbox/libvirt-sandbox-config.c b/libvirt-sandbox/libvirt-sandbox-config.c
index b1525a1..af21dbc 100644
--- a/libvirt-sandbox/libvirt-sandbox-config.c
+++ b/libvirt-sandbox/libvirt-sandbox-config.c
@@ -911,6 +911,8 @@ gboolean gvir_sandbox_config_add_network_strv(GVirSandboxConfig *config,
* source=private,address=192.168.122.1/24%192.168.122.255,
* address=192.168.122.1/24%192.168.122.255,address=2001:212::204:2/64
* route=192.168.122.255/24%192.168.1.1
+ * filter=clean-traffic
+ * filter.ip=192.168.122.1
*/
gboolean gvir_sandbox_config_add_network_opts(GVirSandboxConfig *config,
const gchar *network,
@@ -924,8 +926,10 @@ gboolean gvir_sandbox_config_add_network_opts(GVirSandboxConfig *config,
gchar **params = g_strsplit(network, ",", 50);
gsize j = 0;
GVirSandboxConfigNetwork *net;
+ GVirSandboxConfigNetworkFilterref *filter;
net = gvir_sandbox_config_network_new();
+ filter = gvir_sandbox_config_network_filterref_new();
gvir_sandbox_config_network_set_dhcp(net, FALSE);
while (params && params[j]) {
@@ -947,6 +951,40 @@ gboolean gvir_sandbox_config_add_network_opts(GVirSandboxConfig *config,
} else if (g_str_has_prefix(param, "mac=")) {
gvir_sandbox_config_network_set_mac(net,
param + strlen("mac="));
+ } else if (g_str_has_prefix(param, "filter.")) {
+ GVirSandboxConfigNetworkFilterrefParameter *filter_param;
+ gchar *tail = g_strdup(param + strlen("filter."));
+ gchar *equ = g_strrstr(tail, "=");
+ gchar *name, *name_up, *value;
+
+ if (equ == NULL) {
+ g_free(tail);
+ g_set_error(error, GVIR_SANDBOX_CONFIG_ERROR, 0,
+ _("No assignment in filter parameter configuration"));
+ g_object_unref(net);
+ goto cleanup;
+ }
+
+ name = g_strndup(tail, equ - tail);
+ value = g_strdup(equ + 1);
+ /* Convert to upcase for convenience. */
+ name_up = g_ascii_strup(name, -1);
+ g_free(name);
+
+ filter_param = gvir_sandbox_config_network_filterref_parameter_new();
+ gvir_sandbox_config_network_filterref_parameter_set_name(filter_param, name_up);
+ gvir_sandbox_config_network_filterref_parameter_set_value(filter_param, value);
+ gvir_sandbox_config_network_filterref_add_parameter(filter, filter_param);
+
+ g_free(tail);
+ g_free(name_up);
+ g_free(value);
+ } else if (g_str_has_prefix(param, "filter=")) {
+ gchar *name = g_strdup(param + strlen("filter="));
+
+ gvir_sandbox_config_network_filterref_set_filter(filter, name);
+ gvir_sandbox_config_network_set_filterref(net, filter);
+ g_free(name);
} else if (g_str_has_prefix(param, "address=")) {
GVirSandboxConfigNetworkAddress *addr;
GInetAddress *primaryaddr;
@@ -1090,6 +1128,7 @@ gboolean gvir_sandbox_config_add_network_opts(GVirSandboxConfig *config,
ret = TRUE;
cleanup:
+ g_object_unref(filter);
return ret;
}
diff --git a/libvirt-sandbox/libvirt-sandbox.h b/libvirt-sandbox/libvirt-sandbox.h
index a3f0b2c..7a2d3bf 100644
--- a/libvirt-sandbox/libvirt-sandbox.h
+++ b/libvirt-sandbox/libvirt-sandbox.h
@@ -37,6 +37,8 @@
#include <libvirt-sandbox/libvirt-sandbox-config-mount-guest-bind.h>
#include <libvirt-sandbox/libvirt-sandbox-config-mount-ram.h>
#include <libvirt-sandbox/libvirt-sandbox-config-network-address.h>
+#include <libvirt-sandbox/libvirt-sandbox-config-network-filterref-parameter.h>
+#include <libvirt-sandbox/libvirt-sandbox-config-network-filterref.h>
#include <libvirt-sandbox/libvirt-sandbox-config-network-route.h>
#include <libvirt-sandbox/libvirt-sandbox-config-network.h>
#include <libvirt-sandbox/libvirt-sandbox-config.h>
diff --git a/libvirt-sandbox/libvirt-sandbox.sym b/libvirt-sandbox/libvirt-sandbox.sym
index 7b7c8be..02c69a3 100644
--- a/libvirt-sandbox/libvirt-sandbox.sym
+++ b/libvirt-sandbox/libvirt-sandbox.sym
@@ -44,6 +44,7 @@ LIBVIRT_SANDBOX_0.2.1 {
gvir_sandbox_config_mount_ram_set_usage;
gvir_sandbox_config_network_add_address;
+ gvir_sandbox_config_network_set_filterref;
gvir_sandbox_config_network_add_route;
gvir_sandbox_config_network_get_type;
gvir_sandbox_config_network_get_dhcp;
@@ -51,6 +52,7 @@ LIBVIRT_SANDBOX_0.2.1 {
gvir_sandbox_config_network_get_source;
gvir_sandbox_config_network_get_routes;
gvir_sandbox_config_network_get_addresses;
+ gvir_sandbox_config_network_get_filterref;
gvir_sandbox_config_network_new;
gvir_sandbox_config_network_set_dhcp;
gvir_sandbox_config_network_set_mac;
@@ -65,6 +67,18 @@ LIBVIRT_SANDBOX_0.2.1 {
gvir_sandbox_config_network_address_set_primary;
gvir_sandbox_config_network_address_set_prefix;
+ gvir_sandbox_config_network_filterref_get_type;
+ gvir_sandbox_config_network_filterref_new;
+ gvir_sandbox_config_network_filterref_get_filter;
+ gvir_sandbox_config_network_filterref_set_filter;
+
+ gvir_sandbox_config_network_filterref_parameter_get_type;
+ gvir_sandbox_config_network_filterref_parameter_new;
+ gvir_sandbox_config_network_filterref_parameter_get_name;
+ gvir_sandbox_config_network_filterref_parameter_set_name;
+ gvir_sandbox_config_network_filterref_parameter_get_value;
+ gvir_sandbox_config_network_filterref_parameter_set_value;
+
gvir_sandbox_config_network_route_get_type;
gvir_sandbox_config_network_route_get_prefix;
gvir_sandbox_config_network_route_get_gateway;
--
1.8.1.4
1
0