util: Introduce virMACMap module

This module will be used to track:

  <domain, mac address list>

pairs. It will be important to know these mappings without
libvirt connection (that is from a JSON file), because NSS
module will use those to provide better host name translation.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
Michal Privoznik
2016-12-06 13:33:18 +01:00
parent b9b664c5a8
commit 86980bc75c
12 changed files with 794 additions and 0 deletions
+14
View File
@@ -144,6 +144,7 @@ EXTRA_DIST = \
vircgroupdata \
virconfdata \
virfiledata \
virmacmaptestdata \
virmock.h \
virnetdaemondata \
virnetdevtestdata \
@@ -191,6 +192,7 @@ test_programs = virshtest sockettest \
domainconftest \
virhostdevtest \
vircaps2xmltest \
virmacmaptest \
virnetdevtest \
virtypedparamtest \
$(NULL)
@@ -406,6 +408,7 @@ test_libraries = libshunload.la \
virhostcpumock.la \
nssmock.la \
domaincapsmock.la \
virmacmapmock.la \
$(NULL)
if WITH_QEMU
test_libraries += libqemumonitortestutils.la \
@@ -1137,6 +1140,17 @@ nsslinktest_CFLAGS = \
nsslinktest_LDADD = ../tools/nss/libnss_libvirt_impl.la
nsslinktest_LDFLAGS = $(NULL)
virmacmapmock_la_SOURCES = \
virmacmapmock.c
virmacmapmock_la_CFLAGS = $(AM_CFLAGS)
virmacmapmock_la_LDFLAGS = $(MOCKLIBS_LDFLAGS)
virmacmapmock_la_LIBADD = $(MOCKLIBS_LIBS)
virmacmaptest_SOURCES = \
virmacmaptest.c testutils.h testutils.c
virmacmaptest_CLFAGS = $(AM_CFLAGS);
virmacmaptest_LDADD = $(LDADDS)
virnetdevtest_SOURCES = \
virnetdevtest.c testutils.h testutils.c
virnetdevtest_CFLAGS = $(AM_CFLAGS) $(LIBNL_CFLAGS)
+29
View File
@@ -0,0 +1,29 @@
/*
* Copyright (C) 2016 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, see
* <http://www.gnu.org/licenses/>.
*
* Author: Michal Privoznik <mprivozn@redhat.com>
*/
#include <config.h>
#include "virrandom.h"
uint64_t virRandomBits(int nbits ATTRIBUTE_UNUSED)
{
return 4; /* chosen by fair dice roll.
guaranteed to be random. */
}
+232
View File
@@ -0,0 +1,232 @@
/*
* Copyright (C) 2016 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, see
* <http://www.gnu.org/licenses/>.
*
* Author: Michal Privoznik <mprivozn@redhat.com>
*/
#include <config.h>
#include "testutils.h"
#include "virmacmap.h"
#define VIR_FROM_THIS VIR_FROM_NONE
struct testData {
const char *file;
const char *domain;
const char * const * macs;
virMacMapPtr mgr;
};
static int
testMACLookup(const void *opaque)
{
const struct testData *data = opaque;
virMacMapPtr mgr = NULL;
const char * const * macs;
size_t i, j;
char *file = NULL;
int ret = -1;
if (virAsprintf(&file, "%s/virmacmaptestdata/%s.json",
abs_srcdir, data->file) < 0)
goto cleanup;
if (!(mgr = virMacMapNew(file)))
goto cleanup;
macs = virMacMapLookup(mgr, data->domain);
for (i = 0; macs && macs[i]; i++) {
for (j = 0; data->macs && data->macs[j]; j++) {
if (STREQ(macs[i], data->macs[j]))
break;
}
if (!data->macs || !data->macs[j]) {
fprintf(stderr,
"Unexpected %s in the returned list of MACs\n", macs[i]);
goto cleanup;
}
}
for (i = 0; data->macs && data->macs[i]; i++) {
for (j = 0; macs && macs[j]; j++) {
if (STREQ(data->macs[i], macs[j]))
break;
}
if (!macs || !macs[j]) {
fprintf(stderr,
"Expected %s in the returned list of MACs\n", data->macs[i]);
goto cleanup;
}
}
ret = 0;
cleanup:
VIR_FREE(file);
virObjectUnref(mgr);
return ret;
}
static int
testMACRemove(const void *opaque)
{
const struct testData *data = opaque;
virMacMapPtr mgr = NULL;
const char * const * macs;
size_t i;
char *file = NULL;
int ret = -1;
if (virAsprintf(&file, "%s/virmacmaptestdata/%s.json",
abs_srcdir, data->file) < 0)
goto cleanup;
if (!(mgr = virMacMapNew(file)))
goto cleanup;
for (i = 0; data->macs && data->macs[i]; i++) {
if (virMacMapRemove(mgr, data->domain, data->macs[i]) < 0) {
fprintf(stderr,
"Error when removing %s from the list of MACs\n", data->macs[i]);
goto cleanup;
}
}
if ((macs = virMacMapLookup(mgr, data->domain))) {
fprintf(stderr,
"Not removed all MACs for domain %s: %s\n", data->domain, macs[0]);
goto cleanup;
}
ret = 0;
cleanup:
VIR_FREE(file);
virObjectUnref(mgr);
return ret;
}
static int
testMACFlush(const void *opaque)
{
const struct testData *data = opaque;
char *file = NULL;
char *str = NULL;
int ret = -1;
if (virAsprintf(&file, "%s/virmacmaptestdata/%s.json",
abs_srcdir, data->file) < 0)
goto cleanup;
if (virMacMapDumpStr(data->mgr, &str) < 0)
goto cleanup;
if (virTestCompareToFile(str, file) < 0)
goto cleanup;
ret = 0;
cleanup:
VIR_FREE(file);
VIR_FREE(str);
return ret;
}
static int
mymain(void)
{
int ret = 0;
virMacMapPtr mgr = NULL;
#define DO_TEST_BASIC(f, d, ...) \
do { \
const char * const m[] = {__VA_ARGS__, NULL }; \
struct testData data = {.file = f, .domain = d, .macs = m}; \
if (virTestRun("Lookup " #d " in " #f, \
testMACLookup, &data) < 0) \
ret = -1; \
if (virTestRun("Remove " #d " in " #f, \
testMACRemove, &data) < 0) \
ret = -1; \
} while (0)
#define DO_TEST_FLUSH_PROLOGUE \
if (!(mgr = virMacMapNew(NULL))) \
ret = -1;
#define DO_TEST_FLUSH(d, ...) \
do { \
const char * const m[] = {__VA_ARGS__, NULL }; \
size_t i; \
for (i = 0; m[i]; i++) { \
if (virMacMapAdd(mgr, d, m[i]) < 0) { \
virObjectUnref(mgr); \
mgr = NULL; \
ret = -1; \
} \
} \
} while (0)
#define DO_TEST_FLUSH_EPILOGUE(f) \
do { \
struct testData data = {.file = f, .mgr = mgr}; \
if (virTestRun("Flush " #f, testMACFlush, &data) < 0) \
ret = -1; \
virObjectUnref(mgr); \
mgr = NULL; \
} while (0)
DO_TEST_BASIC("empty", "none", NULL);
DO_TEST_BASIC("simple", "f24", "aa:bb:cc:dd:ee:ff");
DO_TEST_BASIC("simple2", "f24", "aa:bb:cc:dd:ee:ff", "a1:b2:c3:d4:e5:f6");
DO_TEST_BASIC("simple2", "f25", "00:11:22:33:44:55", "aa:bb:cc:00:11:22");
DO_TEST_FLUSH_PROLOGUE;
DO_TEST_FLUSH_EPILOGUE("empty");
DO_TEST_FLUSH_PROLOGUE;
DO_TEST_FLUSH("f24", "aa:bb:cc:dd:ee:ff");
DO_TEST_FLUSH_EPILOGUE("simple");
DO_TEST_FLUSH_PROLOGUE;
DO_TEST_FLUSH("f24", "aa:bb:cc:dd:ee:ff", "a1:b2:c3:d4:e5:f6");
DO_TEST_FLUSH("f25", "00:11:22:33:44:55", "aa:bb:cc:00:11:22");
DO_TEST_FLUSH_EPILOGUE("simple2");
DO_TEST_FLUSH_PROLOGUE;
DO_TEST_FLUSH("dom0", "e1:81:5d:f3:41:57", "76:0a:2a:a0:51:86", "01:c7:fc:01:c7:fc");
DO_TEST_FLUSH("dom0", "8e:82:53:60:32:4a", "14:7a:25:dc:7d:a0", "f8:d7:75:f8:d7:75");
DO_TEST_FLUSH("dom0", "73:d2:50:fb:0f:b1", "82:ee:a7:9b:e3:69", "a8:b4:cb:a8:b4:cb");
DO_TEST_FLUSH("dom0", "7e:81:86:0f:0b:fb", "94:e2:00:d9:4c:70", "dc:7b:83:dc:7b:83");
DO_TEST_FLUSH("dom0", "d1:19:a5:a1:52:a8", "22:03:a0:bf:cb:4a", "e3:c7:f8:e3:c7:f8");
DO_TEST_FLUSH("dom0", "aa:bf:3f:4f:21:8d", "28:67:45:72:8f:47", "eb:08:cd:eb:08:cd");
DO_TEST_FLUSH("dom0", "bd:f8:a7:e5:e2:bd", "c7:80:e3:b9:18:4d", "ce:da:c0:ce:da:c0");
DO_TEST_FLUSH("dom1", "8b:51:1d:9f:2f:29", "7c:ae:4c:3e:e1:11", "c6:68:4e:98:ff:6a");
DO_TEST_FLUSH("dom1", "43:0e:33:a1:3f:0f", "7a:3e:ed:bb:15:27", "b1:17:fd:95:d2:1b");
DO_TEST_FLUSH("dom1", "9e:89:49:99:51:0e", "89:b4:3f:08:88:2c", "54:0b:4c:e2:0a:39");
DO_TEST_FLUSH("dom1", "bb:88:07:19:51:9d", "b7:f1:1a:40:a2:95", "88:94:39:a3:90:b4");
DO_TEST_FLUSH_EPILOGUE("complex");
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}
VIRT_TEST_MAIN_PRELOAD(mymain, abs_builddir "/.libs/virmacmapmock.so")
+45
View File
@@ -0,0 +1,45 @@
[
{
"domain": "dom0",
"macs": [
"e1:81:5d:f3:41:57",
"76:0a:2a:a0:51:86",
"01:c7:fc:01:c7:fc",
"8e:82:53:60:32:4a",
"14:7a:25:dc:7d:a0",
"f8:d7:75:f8:d7:75",
"73:d2:50:fb:0f:b1",
"82:ee:a7:9b:e3:69",
"a8:b4:cb:a8:b4:cb",
"7e:81:86:0f:0b:fb",
"94:e2:00:d9:4c:70",
"dc:7b:83:dc:7b:83",
"d1:19:a5:a1:52:a8",
"22:03:a0:bf:cb:4a",
"e3:c7:f8:e3:c7:f8",
"aa:bf:3f:4f:21:8d",
"28:67:45:72:8f:47",
"eb:08:cd:eb:08:cd",
"bd:f8:a7:e5:e2:bd",
"c7:80:e3:b9:18:4d",
"ce:da:c0:ce:da:c0"
]
},
{
"domain": "dom1",
"macs": [
"8b:51:1d:9f:2f:29",
"7c:ae:4c:3e:e1:11",
"c6:68:4e:98:ff:6a",
"43:0e:33:a1:3f:0f",
"7a:3e:ed:bb:15:27",
"b1:17:fd:95:d2:1b",
"9e:89:49:99:51:0e",
"89:b4:3f:08:88:2c",
"54:0b:4c:e2:0a:39",
"bb:88:07:19:51:9d",
"b7:f1:1a:40:a2:95",
"88:94:39:a3:90:b4"
]
}
]
+3
View File
@@ -0,0 +1,3 @@
[
]
+8
View File
@@ -0,0 +1,8 @@
[
{
"domain": "f24",
"macs": [
"aa:bb:cc:dd:ee:ff"
]
}
]
+16
View File
@@ -0,0 +1,16 @@
[
{
"domain": "f25",
"macs": [
"00:11:22:33:44:55",
"aa:bb:cc:00:11:22"
]
},
{
"domain": "f24",
"macs": [
"aa:bb:cc:dd:ee:ff",
"a1:b2:c3:d4:e5:f6"
]
}
]