Blame SOURCES/libvirt-qemu-qemuMonitorQueryRxFilter-retrieve-guest-netdev-rx-filter.patch

9119d9
From 81c354a5025995d3e5c88b63a3de64f9c0731f20 Mon Sep 17 00:00:00 2001
9119d9
Message-Id: <81c354a5025995d3e5c88b63a3de64f9c0731f20@dist-git>
9119d9
From: Laine Stump <laine@laine.org>
9119d9
Date: Mon, 3 Nov 2014 10:00:18 -0500
9119d9
Subject: [PATCH] qemu: qemuMonitorQueryRxFilter - retrieve guest netdev
9119d9
 rx-filter
9119d9
9119d9
https://bugzilla.redhat.com/show_bug.cgi?id=848199
9119d9
9119d9
This function can be called at any time to get the current status of a
9119d9
guest's network device rx-filter. In particular it is useful to call
9119d9
after libvirt recieves a NIC_RX_FILTER_CHANGED event - this event only
9119d9
tells you that something has changed in the rx-filter, the details are
9119d9
retrieved with the query-rx-filter monitor command (only available in
9119d9
the json monitor). The command sent to the qemu monitor looks like this:
9119d9
9119d9
  {"execute":"query-rx-filter", "arguments": {"name":"net2"} }'
9119d9
9119d9
and the results will look something like this:
9119d9
9119d9
{
9119d9
    "return": [
9119d9
        {
9119d9
            "promiscuous": false,
9119d9
            "name": "net2",
9119d9
            "main-mac": "52:54:00:98:2d:e3",
9119d9
            "unicast": "normal",
9119d9
            "vlan": "normal",
9119d9
            "vlan-table": [
9119d9
                42,
9119d9
                0
9119d9
            ],
9119d9
            "unicast-table": [
9119d9
9119d9
            ],
9119d9
            "multicast": "normal",
9119d9
            "multicast-overflow": false,
9119d9
            "unicast-overflow": false,
9119d9
            "multicast-table": [
9119d9
                "33:33:ff:98:2d:e3",
9119d9
                "01:80:c2:00:00:21",
9119d9
                "01:00:5e:00:00:fb",
9119d9
                "33:33:ff:98:2d:e2",
9119d9
                "01:00:5e:00:00:01",
9119d9
                "33:33:00:00:00:01"
9119d9
            ],
9119d9
            "broadcast-allowed": false
9119d9
        }
9119d9
    ],
9119d9
    "id": "libvirt-14"
9119d9
}
9119d9
9119d9
This is all parsed from JSON into a virNetDevRxFilter object for
9119d9
easier consumption. (unicast-table is usually empty, but is also an
9119d9
array of mac addresses similar to multicast-table).
9119d9
9119d9
(NB: LIBNL_CFLAGS was added to tests/Makefile.am because virnetdev.h
9119d9
now includes util/virnetlink.h, which includes netlink/msg.h when
9119d9
appropriate. Without LIBNL_CFLAGS, gcc can't find that file (if
9119d9
libnl/netlink isn't available, LIBNL_CFLAGS will be empty and
9119d9
virnetlink.h won't try to include netlink/msg.h anyway).)
9119d9
9119d9
(cherry picked from commit ab989962d4c2ef9045a9b8344b8e6f4094027c7c)
9119d9
9119d9
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
9119d9
---
9119d9
 src/qemu/qemu_monitor.c      |  26 ++++++
9119d9
 src/qemu/qemu_monitor.h      |   4 +
9119d9
 src/qemu/qemu_monitor_json.c | 215 +++++++++++++++++++++++++++++++++++++++++++
9119d9
 src/qemu/qemu_monitor_json.h |   3 +
9119d9
 tests/Makefile.am            |   1 +
9119d9
 5 files changed, 249 insertions(+)
9119d9
9119d9
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
9119d9
index 8e14366..be8d60b 100644
9119d9
--- a/src/qemu/qemu_monitor.c
9119d9
+++ b/src/qemu/qemu_monitor.c
9119d9
@@ -2933,6 +2933,32 @@ int qemuMonitorRemoveNetdev(qemuMonitorPtr mon,
9119d9
 }
9119d9
 
9119d9
 
9119d9
+int
9119d9
+qemuMonitorQueryRxFilter(qemuMonitorPtr mon, const char *alias,
9119d9
+                         virNetDevRxFilterPtr *filter)
9119d9
+{
9119d9
+    int ret = -1;
9119d9
+    VIR_DEBUG("mon=%p alias=%s filter=%p",
9119d9
+              mon, alias, filter);
9119d9
+
9119d9
+    if (!mon) {
9119d9
+        virReportError(VIR_ERR_INVALID_ARG, "%s",
9119d9
+                       _("monitor must not be NULL"));
9119d9
+        return -1;
9119d9
+    }
9119d9
+
9119d9
+
9119d9
+    VIR_DEBUG("mon=%p, alias=%s", mon, alias);
9119d9
+
9119d9
+    if (mon->json)
9119d9
+        ret = qemuMonitorJSONQueryRxFilter(mon, alias, filter);
9119d9
+    else
9119d9
+        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
9119d9
+                       _("query-rx-filter requires JSON monitor"));
9119d9
+    return ret;
9119d9
+}
9119d9
+
9119d9
+
9119d9
 int qemuMonitorGetPtyPaths(qemuMonitorPtr mon,
9119d9
                            virHashTablePtr paths)
9119d9
 {
9119d9
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
9119d9
index 5bffca8..cfcaf30 100644
9119d9
--- a/src/qemu/qemu_monitor.h
9119d9
+++ b/src/qemu/qemu_monitor.h
9119d9
@@ -31,6 +31,7 @@
9119d9
 # include "virbitmap.h"
9119d9
 # include "virhash.h"
9119d9
 # include "virjson.h"
9119d9
+# include "virnetdev.h"
9119d9
 # include "device_conf.h"
9119d9
 # include "cpu/cpu.h"
9119d9
 
9119d9
@@ -627,6 +628,9 @@ int qemuMonitorAddNetdev(qemuMonitorPtr mon,
9119d9
 int qemuMonitorRemoveNetdev(qemuMonitorPtr mon,
9119d9
                             const char *alias);
9119d9
 
9119d9
+int qemuMonitorQueryRxFilter(qemuMonitorPtr mon, const char *alias,
9119d9
+                             virNetDevRxFilterPtr *filter);
9119d9
+
9119d9
 int qemuMonitorGetPtyPaths(qemuMonitorPtr mon,
9119d9
                            virHashTablePtr paths);
9119d9
 
9119d9
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
9119d9
index cad6be8..7a6d1e1 100644
9119d9
--- a/src/qemu/qemu_monitor_json.c
9119d9
+++ b/src/qemu/qemu_monitor_json.c
9119d9
@@ -3297,6 +3297,221 @@ int qemuMonitorJSONRemoveNetdev(qemuMonitorPtr mon,
9119d9
 }
9119d9
 
9119d9
 
9119d9
+static int
9119d9
+qemuMonitorJSONQueryRxFilterParse(virJSONValuePtr msg,
9119d9
+                                  virNetDevRxFilterPtr *filter)
9119d9
+{
9119d9
+    int ret = -1;
9119d9
+    const char *tmp;
9119d9
+    virJSONValuePtr returnArray, entry, table, element;
9119d9
+    int nTable;
9119d9
+    size_t i;
9119d9
+    virNetDevRxFilterPtr fil = virNetDevRxFilterNew();
9119d9
+
9119d9
+    if (!fil)
9119d9
+        goto cleanup;
9119d9
+
9119d9
+    if (!(returnArray = virJSONValueObjectGet(msg, "return"))) {
9119d9
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
9119d9
+                       _("query-rx-filter reply was missing return data"));
9119d9
+        goto cleanup;
9119d9
+    }
9119d9
+    if (returnArray->type != VIR_JSON_TYPE_ARRAY) {
9119d9
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
9119d9
+                       _("query-rx-filter return data was not an array"));
9119d9
+        goto cleanup;
9119d9
+    }
9119d9
+    if (!(entry = virJSONValueArrayGet(returnArray, 0))) {
9119d9
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
9119d9
+                       _("query -rx-filter return data missing array element"));
9119d9
+        goto cleanup;
9119d9
+    }
9119d9
+
9119d9
+    if (!(tmp = virJSONValueObjectGetString(entry, "name"))) {
9119d9
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
9119d9
+                       _("Missing or invalid name "
9119d9
+                         "in query-rx-filter response"));
9119d9
+        goto cleanup;
9119d9
+    }
9119d9
+    if (VIR_STRDUP(fil->name, tmp) < 0)
9119d9
+        goto cleanup;
9119d9
+    if ((!(tmp = virJSONValueObjectGetString(entry, "main-mac"))) ||
9119d9
+        virMacAddrParse(tmp, &fil->mac) < 0) {
9119d9
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
9119d9
+                       _("Missing or invalid 'main-mac' "
9119d9
+                         "in query-rx-filter response"));
9119d9
+        goto cleanup;
9119d9
+    }
9119d9
+    if (virJSONValueObjectGetBoolean(entry, "promiscuous",
9119d9
+                                     &fil->promiscuous) < 0) {
9119d9
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
9119d9
+                       _("Missing or invalid 'promiscuous' "
9119d9
+                         "in query-rx-filter response"));
9119d9
+        goto cleanup;
9119d9
+    }
9119d9
+    if (virJSONValueObjectGetBoolean(entry, "broadcast-allowed",
9119d9
+                                     &fil->broadcastAllowed) < 0) {
9119d9
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
9119d9
+                       _("Missing or invalid 'broadcast-allowed' "
9119d9
+                         "in query-rx-filter response"));
9119d9
+        goto cleanup;
9119d9
+    }
9119d9
+
9119d9
+    if ((!(tmp = virJSONValueObjectGetString(entry, "unicast"))) ||
9119d9
+        ((fil->unicast.mode
9119d9
+          = virNetDevRxFilterModeTypeFromString(tmp)) < 0)) {
9119d9
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
9119d9
+                       _("Missing or invalid 'unicast' "
9119d9
+                         "in query-rx-filter response"));
9119d9
+        goto cleanup;
9119d9
+    }
9119d9
+    if (virJSONValueObjectGetBoolean(entry, "unicast-overflow",
9119d9
+                                     &fil->unicast.overflow) < 0) {
9119d9
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
9119d9
+                       _("Missing or invalid 'unicast-overflow' "
9119d9
+                         "in query-rx-filter response"));
9119d9
+        goto cleanup;
9119d9
+    }
9119d9
+    if ((!(table = virJSONValueObjectGet(entry, "unicast-table"))) ||
9119d9
+        ((nTable = virJSONValueArraySize(table)) < 0)) {
9119d9
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
9119d9
+                       _("Missing or invalid 'unicast-table' array "
9119d9
+                         "in query-rx-filter response"));
9119d9
+        goto cleanup;
9119d9
+    }
9119d9
+    if (VIR_ALLOC_N(fil->unicast.table, nTable))
9119d9
+        goto cleanup;
9119d9
+    for (i = 0; i < nTable; i++) {
9119d9
+        if (!(element = virJSONValueArrayGet(table, i)) ||
9119d9
+            !(tmp = virJSONValueGetString(element))) {
9119d9
+            virReportError(VIR_ERR_INTERNAL_ERROR,
9119d9
+                           _("Missing or invalid element %zu of 'unicast' "
9119d9
+                             "list in query-rx-filter response"), i);
9119d9
+            goto cleanup;
9119d9
+        }
9119d9
+        if (virMacAddrParse(tmp, &fil->unicast.table[i]) < 0) {
9119d9
+            virReportError(VIR_ERR_INTERNAL_ERROR,
9119d9
+                           _("invalid mac address '%s' in 'unicast-table' "
9119d9
+                             "array in query-rx-filter response"), tmp);
9119d9
+            goto cleanup;
9119d9
+        }
9119d9
+    }
9119d9
+    fil->unicast.nTable = nTable;
9119d9
+
9119d9
+    if ((!(tmp = virJSONValueObjectGetString(entry, "multicast"))) ||
9119d9
+        ((fil->multicast.mode
9119d9
+          = virNetDevRxFilterModeTypeFromString(tmp)) < 0)) {
9119d9
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
9119d9
+                       _("Missing or invalid 'multicast' "
9119d9
+                         "in query-rx-filter response"));
9119d9
+        goto cleanup;
9119d9
+    }
9119d9
+    if (virJSONValueObjectGetBoolean(entry, "multicast-overflow",
9119d9
+                                     &fil->multicast.overflow) < 0) {
9119d9
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
9119d9
+                       _("Missing or invalid 'multicast-overflow' "
9119d9
+                         "in query-rx-filter response"));
9119d9
+        goto cleanup;
9119d9
+    }
9119d9
+    if ((!(table = virJSONValueObjectGet(entry, "multicast-table"))) ||
9119d9
+        ((nTable = virJSONValueArraySize(table)) < 0)) {
9119d9
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
9119d9
+                       _("Missing or invalid 'multicast-table' array "
9119d9
+                         "in query-rx-filter response"));
9119d9
+        goto cleanup;
9119d9
+    }
9119d9
+    if (VIR_ALLOC_N(fil->multicast.table, nTable))
9119d9
+        goto cleanup;
9119d9
+    for (i = 0; i < nTable; i++) {
9119d9
+        if (!(element = virJSONValueArrayGet(table, i)) ||
9119d9
+            !(tmp = virJSONValueGetString(element))) {
9119d9
+            virReportError(VIR_ERR_INTERNAL_ERROR,
9119d9
+                           _("Missing or invalid element %zu of 'multicast' "
9119d9
+                             "list in query-rx-filter response"), i);
9119d9
+            goto cleanup;
9119d9
+        }
9119d9
+        if (virMacAddrParse(tmp, &fil->multicast.table[i]) < 0) {
9119d9
+            virReportError(VIR_ERR_INTERNAL_ERROR,
9119d9
+                           _("invalid mac address '%s' in 'multicast-table' "
9119d9
+                             "array in query-rx-filter response"), tmp);
9119d9
+            goto cleanup;
9119d9
+        }
9119d9
+    }
9119d9
+    fil->multicast.nTable = nTable;
9119d9
+
9119d9
+    if ((!(tmp = virJSONValueObjectGetString(entry, "vlan"))) ||
9119d9
+        ((fil->vlan.mode
9119d9
+          = virNetDevRxFilterModeTypeFromString(tmp)) < 0)) {
9119d9
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
9119d9
+                       _("Missing or invalid 'vlan' "
9119d9
+                         "in query-rx-filter response"));
9119d9
+        goto cleanup;
9119d9
+    }
9119d9
+    if ((!(table = virJSONValueObjectGet(entry, "vlan-table"))) ||
9119d9
+        ((nTable = virJSONValueArraySize(table)) < 0)) {
9119d9
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
9119d9
+                       _("Missing or invalid 'vlan-table' array "
9119d9
+                         "in query-rx-filter response"));
9119d9
+        goto cleanup;
9119d9
+    }
9119d9
+    if (VIR_ALLOC_N(fil->vlan.table, nTable))
9119d9
+        goto cleanup;
9119d9
+    for (i = 0; i < nTable; i++) {
9119d9
+        if (!(element = virJSONValueArrayGet(table, i)) ||
9119d9
+            virJSONValueGetNumberUint(element, &fil->vlan.table[i]) < 0) {
9119d9
+            virReportError(VIR_ERR_INTERNAL_ERROR,
9119d9
+                           _("Missing or invalid element %zu of 'vlan-table' "
9119d9
+                             "array in query-rx-filter response"), i);
9119d9
+            goto cleanup;
9119d9
+        }
9119d9
+    }
9119d9
+    fil->vlan.nTable = nTable;
9119d9
+
9119d9
+    ret = 0;
9119d9
+ cleanup:
9119d9
+    if (ret < 0) {
9119d9
+        virNetDevRxFilterFree(fil);
9119d9
+        fil = NULL;
9119d9
+    }
9119d9
+    *filter = fil;
9119d9
+    return ret;
9119d9
+}
9119d9
+
9119d9
+
9119d9
+int
9119d9
+qemuMonitorJSONQueryRxFilter(qemuMonitorPtr mon, const char *alias,
9119d9
+                             virNetDevRxFilterPtr *filter)
9119d9
+{
9119d9
+    int ret = -1;
9119d9
+    virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("query-rx-filter",
9119d9
+                                                     "s:name", alias,
9119d9
+                                                     NULL);
9119d9
+    virJSONValuePtr reply = NULL;
9119d9
+
9119d9
+    if (!cmd)
9119d9
+        goto cleanup;
9119d9
+
9119d9
+    if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
9119d9
+        goto cleanup;
9119d9
+
9119d9
+    if (qemuMonitorJSONQueryRxFilterParse(reply, filter) < 0)
9119d9
+        goto cleanup;
9119d9
+
9119d9
+    ret = 0;
9119d9
+ cleanup:
9119d9
+    if (ret == 0)
9119d9
+        ret = qemuMonitorJSONCheckError(cmd, reply);
9119d9
+
9119d9
+    if (ret < 0) {
9119d9
+        virNetDevRxFilterFree(*filter);
9119d9
+        *filter = NULL;
9119d9
+    }
9119d9
+    virJSONValueFree(cmd);
9119d9
+    virJSONValueFree(reply);
9119d9
+    return ret;
9119d9
+}
9119d9
+
9119d9
+
9119d9
 /*
9119d9
  * Example return data
9119d9
  *
9119d9
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
9119d9
index 289bd11..8d88c6d 100644
9119d9
--- a/src/qemu/qemu_monitor_json.h
9119d9
+++ b/src/qemu/qemu_monitor_json.h
9119d9
@@ -210,6 +210,9 @@ int qemuMonitorJSONAddNetdev(qemuMonitorPtr mon,
9119d9
 int qemuMonitorJSONRemoveNetdev(qemuMonitorPtr mon,
9119d9
                                 const char *alias);
9119d9
 
9119d9
+int qemuMonitorJSONQueryRxFilter(qemuMonitorPtr mon, const char *alias,
9119d9
+                                 virNetDevRxFilterPtr *filter);
9119d9
+
9119d9
 int qemuMonitorJSONGetPtyPaths(qemuMonitorPtr mon,
9119d9
                                virHashTablePtr paths);
9119d9
 
9119d9
diff --git a/tests/Makefile.am b/tests/Makefile.am
9119d9
index d6c3cfb..110effd 100644
9119d9
--- a/tests/Makefile.am
9119d9
+++ b/tests/Makefile.am
9119d9
@@ -35,6 +35,7 @@ AM_CFLAGS = \
9119d9
 	-Dabs_builddir="\"$(abs_builddir)\"" \
9119d9
 	-Dabs_srcdir="\"$(abs_srcdir)\"" \
9119d9
 	$(LIBXML_CFLAGS) \
9119d9
+	$(LIBNL_CFLAGS) \
9119d9
 	$(GNUTLS_CFLAGS) \
9119d9
 	$(SASL_CFLAGS) \
9119d9
 	$(SELINUX_CFLAGS) \
9119d9
-- 
9119d9
2.1.3
9119d9