From: Laine Stump <[email protected]>

This new function sends the command "self-announce" to QEMU, causing
it to inject a series of gratuitous ARP packets (GARP) into the output
stream of one or all guest interfaces, which will force any switches
the same collision domain to update their forwarding db for that
interface.

There are several parameters that control which interfaces the GARP
packets are sent on, as well as their number and interval, but all of
these parameters have sane defaults (even though QEMU's own
self-announce requires they all be specified in the QMP command).

All parameters except the device are just unsigned integers; the QEMU
command accepts a list of interface devices, but it seems much more
likely that someone will either want to announce a single interface,
or all of them, so our function just accepts a single device name that
can be present or not, and puts that single name into a list (in the
rare case that someone wants to announce multiple interfaces but not
all of them, they can call our API multiple times).

Signed-off-by: Laine Stump <[email protected]>
---
 src/qemu/qemu_monitor.c      | 13 +++++++++
 src/qemu/qemu_monitor.h      |  8 ++++++
 src/qemu/qemu_monitor_json.c | 55 ++++++++++++++++++++++++++++++++++++
 src/qemu/qemu_monitor_json.h |  8 ++++++
 4 files changed, 84 insertions(+)

diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index ef83e7b69a..baa78dd6fe 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -4592,3 +4592,16 @@ qemuMonitorBlockLatencyHistogramSet(qemuMonitor *mon,
                                                    boundaries_zone,
                                                    boundaries_flush);
 }
+
+int
+qemuMonitorAnnounceSelf(qemuMonitor *mon,
+                        const char *device,
+                        unsigned int initial,
+                        unsigned int max,
+                        unsigned int rounds,
+                        unsigned int step)
+{
+    QEMU_CHECK_MONITOR(mon);
+
+    return qemuMonitorJSONAnnounceSelf(mon, device, initial, max, rounds, 
step);
+}
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index f93d193d75..c2afb580e4 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -1995,3 +1995,11 @@ qemuMonitorBlockLatencyHistogramSet(qemuMonitor *mon,
                                     unsigned int *boundaries_write,
                                     unsigned int *boundaries_zone,
                                     unsigned int *boundaries_flush);
+
+int
+qemuMonitorAnnounceSelf(qemuMonitor *mon,
+                        const char *device,
+                        unsigned int initial,
+                        unsigned int max,
+                        unsigned int rounds,
+                        unsigned int step);
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 7efd3f443a..074eeb856c 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -9237,3 +9237,58 @@ qemuMonitorJSONBlockLatencyHistogramSet(qemuMonitor *mon,
 
     return qemuMonitorJSONCheckError(cmd, reply);
 }
+
+
+int
+qemuMonitorJSONAnnounceSelf(qemuMonitor *mon,
+                            const char *device,
+                            unsigned int initial,
+                            unsigned int max,
+                            unsigned int rounds,
+                            unsigned int step)
+{
+    g_autoptr(virJSONValue) cmd = NULL;
+    g_autoptr(virJSONValue) reply = NULL;
+    g_autoptr(virJSONValue) devlist = NULL;
+
+    /* announce-self optionally accepts a list of device names, but we
+     * only support a single device name (or none), so we make a
+     * NULL-terminated list with a single item
+     */
+    if (device) {
+        devlist = virJSONValueNewArray();
+        if (virJSONValueArrayAppendString(devlist, device) < 0)
+            return -1;
+    }
+
+    /* all the other parameters are mandatory for QEMU, but we make
+     * them optional to simplify using the API. Since the value 0
+     * would be nonsensical for any of these, we make that the "use a
+     * default value" sentinal. The values we use as default are the
+     * values QEMU will use internally when it does an announce-self
+     * at the end of a migration.
+     */
+    if (!initial)
+        initial = 50;
+    if (!max)
+        max = 550;
+    if (!rounds)
+        rounds = 5;
+    if (!step)
+        step = 50;
+
+    if (!(cmd = qemuMonitorJSONMakeCommand("announce-self",
+                                           "A:interfaces", &devlist,
+                                           "u:initial", initial,
+                                           "u:max", max,
+                                           "u:rounds", rounds,
+                                           "u:step", step,
+                                           NULL))) {
+        return -1;
+    }
+
+    if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
+        return -1;
+
+    return qemuMonitorJSONCheckError(cmd, reply);
+}
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index 5034c8d23d..f4c093d717 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -828,3 +828,11 @@ qemuMonitorJSONBlockLatencyHistogramSet(qemuMonitor *mon,
                                         unsigned int *boundaries_write,
                                         unsigned int *boundaries_zone,
                                         unsigned int *boundaries_flush);
+
+int
+qemuMonitorJSONAnnounceSelf(qemuMonitor *mon,
+                            const char *device,
+                            unsigned int initial,
+                            unsigned int max,
+                            unsigned int rounds,
+                            unsigned int step);
-- 
2.54.0

Reply via email to