mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-21 19:02:25 +00:00
qemu: qemuMonitorQueryRxFilter - retrieve guest netdev rx-filter
This function can be called at any time to get the current status of a guest's network device rx-filter. In particular it is useful to call after libvirt recieves a NIC_RX_FILTER_CHANGED event - this event only tells you that something has changed in the rx-filter, the details are retrieved with the query-rx-filter monitor command (only available in the json monitor). The command sent to the qemu monitor looks like this: {"execute":"query-rx-filter", "arguments": {"name":"net2"} }' and the results will look something like this: { "return": [ { "promiscuous": false, "name": "net2", "main-mac": "52:54:00:98:2d:e3", "unicast": "normal", "vlan": "normal", "vlan-table": [ 42, 0 ], "unicast-table": [ ], "multicast": "normal", "multicast-overflow": false, "unicast-overflow": false, "multicast-table": [ "33:33:ff:98:2d:e3", "01:80:c2:00:00:21", "01:00:5e:00:00:fb", "33:33:ff:98:2d:e2", "01:00:5e:00:00:01", "33:33:00:00:00:01" ], "broadcast-allowed": false } ], "id": "libvirt-14" } This is all parsed from JSON into a virNetDevRxFilter object for easier consumption. (unicast-table is usually empty, but is also an array of mac addresses similar to multicast-table). (NB: LIBNL_CFLAGS was added to tests/Makefile.am because virnetdev.h now includes util/virnetlink.h, which includes netlink/msg.h when appropriate. Without LIBNL_CFLAGS, gcc can't find that file (if libnl/netlink isn't available, LIBNL_CFLAGS will be empty and virnetlink.h won't try to include netlink/msg.h anyway).)
This commit is contained in:
parent
aa7c595a31
commit
ab989962d4
@ -2929,6 +2929,32 @@ int qemuMonitorRemoveNetdev(qemuMonitorPtr mon,
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
qemuMonitorQueryRxFilter(qemuMonitorPtr mon, const char *alias,
|
||||
virNetDevRxFilterPtr *filter)
|
||||
{
|
||||
int ret = -1;
|
||||
VIR_DEBUG("mon=%p alias=%s filter=%p",
|
||||
mon, alias, filter);
|
||||
|
||||
if (!mon) {
|
||||
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
||||
_("monitor must not be NULL"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
VIR_DEBUG("mon=%p, alias=%s", mon, alias);
|
||||
|
||||
if (mon->json)
|
||||
ret = qemuMonitorJSONQueryRxFilter(mon, alias, filter);
|
||||
else
|
||||
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
||||
_("query-rx-filter requires JSON monitor"));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int qemuMonitorGetPtyPaths(qemuMonitorPtr mon,
|
||||
virHashTablePtr paths)
|
||||
{
|
||||
|
@ -31,6 +31,7 @@
|
||||
# include "virbitmap.h"
|
||||
# include "virhash.h"
|
||||
# include "virjson.h"
|
||||
# include "virnetdev.h"
|
||||
# include "device_conf.h"
|
||||
# include "cpu/cpu.h"
|
||||
|
||||
@ -627,6 +628,9 @@ int qemuMonitorAddNetdev(qemuMonitorPtr mon,
|
||||
int qemuMonitorRemoveNetdev(qemuMonitorPtr mon,
|
||||
const char *alias);
|
||||
|
||||
int qemuMonitorQueryRxFilter(qemuMonitorPtr mon, const char *alias,
|
||||
virNetDevRxFilterPtr *filter);
|
||||
|
||||
int qemuMonitorGetPtyPaths(qemuMonitorPtr mon,
|
||||
virHashTablePtr paths);
|
||||
|
||||
|
@ -3313,6 +3313,221 @@ int qemuMonitorJSONRemoveNetdev(qemuMonitorPtr mon,
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
qemuMonitorJSONQueryRxFilterParse(virJSONValuePtr msg,
|
||||
virNetDevRxFilterPtr *filter)
|
||||
{
|
||||
int ret = -1;
|
||||
const char *tmp;
|
||||
virJSONValuePtr returnArray, entry, table, element;
|
||||
int nTable;
|
||||
size_t i;
|
||||
virNetDevRxFilterPtr fil = virNetDevRxFilterNew();
|
||||
|
||||
if (!fil)
|
||||
goto cleanup;
|
||||
|
||||
if (!(returnArray = virJSONValueObjectGet(msg, "return"))) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("query-rx-filter reply was missing return data"));
|
||||
goto cleanup;
|
||||
}
|
||||
if (returnArray->type != VIR_JSON_TYPE_ARRAY) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("query-rx-filter return data was not an array"));
|
||||
goto cleanup;
|
||||
}
|
||||
if (!(entry = virJSONValueArrayGet(returnArray, 0))) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("query -rx-filter return data missing array element"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!(tmp = virJSONValueObjectGetString(entry, "name"))) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Missing or invalid name "
|
||||
"in query-rx-filter response"));
|
||||
goto cleanup;
|
||||
}
|
||||
if (VIR_STRDUP(fil->name, tmp) < 0)
|
||||
goto cleanup;
|
||||
if ((!(tmp = virJSONValueObjectGetString(entry, "main-mac"))) ||
|
||||
virMacAddrParse(tmp, &fil->mac) < 0) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Missing or invalid 'main-mac' "
|
||||
"in query-rx-filter response"));
|
||||
goto cleanup;
|
||||
}
|
||||
if (virJSONValueObjectGetBoolean(entry, "promiscuous",
|
||||
&fil->promiscuous) < 0) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Missing or invalid 'promiscuous' "
|
||||
"in query-rx-filter response"));
|
||||
goto cleanup;
|
||||
}
|
||||
if (virJSONValueObjectGetBoolean(entry, "broadcast-allowed",
|
||||
&fil->broadcastAllowed) < 0) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Missing or invalid 'broadcast-allowed' "
|
||||
"in query-rx-filter response"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((!(tmp = virJSONValueObjectGetString(entry, "unicast"))) ||
|
||||
((fil->unicast.mode
|
||||
= virNetDevRxFilterModeTypeFromString(tmp)) < 0)) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Missing or invalid 'unicast' "
|
||||
"in query-rx-filter response"));
|
||||
goto cleanup;
|
||||
}
|
||||
if (virJSONValueObjectGetBoolean(entry, "unicast-overflow",
|
||||
&fil->unicast.overflow) < 0) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Missing or invalid 'unicast-overflow' "
|
||||
"in query-rx-filter response"));
|
||||
goto cleanup;
|
||||
}
|
||||
if ((!(table = virJSONValueObjectGet(entry, "unicast-table"))) ||
|
||||
((nTable = virJSONValueArraySize(table)) < 0)) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Missing or invalid 'unicast-table' array "
|
||||
"in query-rx-filter response"));
|
||||
goto cleanup;
|
||||
}
|
||||
if (VIR_ALLOC_N(fil->unicast.table, nTable))
|
||||
goto cleanup;
|
||||
for (i = 0; i < nTable; i++) {
|
||||
if (!(element = virJSONValueArrayGet(table, i)) ||
|
||||
!(tmp = virJSONValueGetString(element))) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("Missing or invalid element %zu of 'unicast' "
|
||||
"list in query-rx-filter response"), i);
|
||||
goto cleanup;
|
||||
}
|
||||
if (virMacAddrParse(tmp, &fil->unicast.table[i]) < 0) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("invalid mac address '%s' in 'unicast-table' "
|
||||
"array in query-rx-filter response"), tmp);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
fil->unicast.nTable = nTable;
|
||||
|
||||
if ((!(tmp = virJSONValueObjectGetString(entry, "multicast"))) ||
|
||||
((fil->multicast.mode
|
||||
= virNetDevRxFilterModeTypeFromString(tmp)) < 0)) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Missing or invalid 'multicast' "
|
||||
"in query-rx-filter response"));
|
||||
goto cleanup;
|
||||
}
|
||||
if (virJSONValueObjectGetBoolean(entry, "multicast-overflow",
|
||||
&fil->multicast.overflow) < 0) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Missing or invalid 'multicast-overflow' "
|
||||
"in query-rx-filter response"));
|
||||
goto cleanup;
|
||||
}
|
||||
if ((!(table = virJSONValueObjectGet(entry, "multicast-table"))) ||
|
||||
((nTable = virJSONValueArraySize(table)) < 0)) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Missing or invalid 'multicast-table' array "
|
||||
"in query-rx-filter response"));
|
||||
goto cleanup;
|
||||
}
|
||||
if (VIR_ALLOC_N(fil->multicast.table, nTable))
|
||||
goto cleanup;
|
||||
for (i = 0; i < nTable; i++) {
|
||||
if (!(element = virJSONValueArrayGet(table, i)) ||
|
||||
!(tmp = virJSONValueGetString(element))) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("Missing or invalid element %zu of 'multicast' "
|
||||
"list in query-rx-filter response"), i);
|
||||
goto cleanup;
|
||||
}
|
||||
if (virMacAddrParse(tmp, &fil->multicast.table[i]) < 0) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("invalid mac address '%s' in 'multicast-table' "
|
||||
"array in query-rx-filter response"), tmp);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
fil->multicast.nTable = nTable;
|
||||
|
||||
if ((!(tmp = virJSONValueObjectGetString(entry, "vlan"))) ||
|
||||
((fil->vlan.mode
|
||||
= virNetDevRxFilterModeTypeFromString(tmp)) < 0)) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Missing or invalid 'vlan' "
|
||||
"in query-rx-filter response"));
|
||||
goto cleanup;
|
||||
}
|
||||
if ((!(table = virJSONValueObjectGet(entry, "vlan-table"))) ||
|
||||
((nTable = virJSONValueArraySize(table)) < 0)) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Missing or invalid 'vlan-table' array "
|
||||
"in query-rx-filter response"));
|
||||
goto cleanup;
|
||||
}
|
||||
if (VIR_ALLOC_N(fil->vlan.table, nTable))
|
||||
goto cleanup;
|
||||
for (i = 0; i < nTable; i++) {
|
||||
if (!(element = virJSONValueArrayGet(table, i)) ||
|
||||
virJSONValueGetNumberUint(element, &fil->vlan.table[i]) < 0) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("Missing or invalid element %zu of 'vlan-table' "
|
||||
"array in query-rx-filter response"), i);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
fil->vlan.nTable = nTable;
|
||||
|
||||
ret = 0;
|
||||
cleanup:
|
||||
if (ret < 0) {
|
||||
virNetDevRxFilterFree(fil);
|
||||
fil = NULL;
|
||||
}
|
||||
*filter = fil;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
qemuMonitorJSONQueryRxFilter(qemuMonitorPtr mon, const char *alias,
|
||||
virNetDevRxFilterPtr *filter)
|
||||
{
|
||||
int ret = -1;
|
||||
virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("query-rx-filter",
|
||||
"s:name", alias,
|
||||
NULL);
|
||||
virJSONValuePtr reply = NULL;
|
||||
|
||||
if (!cmd)
|
||||
goto cleanup;
|
||||
|
||||
if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (qemuMonitorJSONQueryRxFilterParse(reply, filter) < 0)
|
||||
goto cleanup;
|
||||
|
||||
ret = 0;
|
||||
cleanup:
|
||||
if (ret == 0)
|
||||
ret = qemuMonitorJSONCheckError(cmd, reply);
|
||||
|
||||
if (ret < 0) {
|
||||
virNetDevRxFilterFree(*filter);
|
||||
*filter = NULL;
|
||||
}
|
||||
virJSONValueFree(cmd);
|
||||
virJSONValueFree(reply);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Example return data
|
||||
*
|
||||
|
@ -210,6 +210,9 @@ int qemuMonitorJSONAddNetdev(qemuMonitorPtr mon,
|
||||
int qemuMonitorJSONRemoveNetdev(qemuMonitorPtr mon,
|
||||
const char *alias);
|
||||
|
||||
int qemuMonitorJSONQueryRxFilter(qemuMonitorPtr mon, const char *alias,
|
||||
virNetDevRxFilterPtr *filter);
|
||||
|
||||
int qemuMonitorJSONGetPtyPaths(qemuMonitorPtr mon,
|
||||
virHashTablePtr paths);
|
||||
|
||||
|
@ -35,6 +35,7 @@ AM_CFLAGS = \
|
||||
-Dabs_builddir="\"$(abs_builddir)\"" \
|
||||
-Dabs_srcdir="\"$(abs_srcdir)\"" \
|
||||
$(LIBXML_CFLAGS) \
|
||||
$(LIBNL_CFLAGS) \
|
||||
$(GNUTLS_CFLAGS) \
|
||||
$(SASL_CFLAGS) \
|
||||
$(SELINUX_CFLAGS) \
|
||||
|
Loading…
x
Reference in New Issue
Block a user