@@ -383,6 +383,7 @@ vhost_scsi=""
vhost_vsock=""
vhost_user=""
vhost_user_fs=""
+awd="no"
kvm="no"
hax="no"
hvf="no"
@@ -1303,6 +1304,10 @@ for opt do
;;
--enable-vhost-user-fs) vhost_user_fs="yes"
;;
+ --disable-awd) awd="no"
+ ;;
+ --enable-awd) awd="yes"
+ ;;
--disable-opengl) opengl="no"
;;
--enable-opengl) opengl="yes"
@@ -1779,6 +1784,7 @@ disabled with --disable-FEATURE, default is enabled if available:
vhost-crypto vhost-user-crypto backend support
vhost-kernel vhost kernel backend support
vhost-user vhost-user backend support
+ awd Advanced Watch Dog support
spice spice
rbd rados block device (rbd)
libiscsi iscsi support
@@ -7002,6 +7008,9 @@ fi
if test "$vhost_user" = "yes" ; then
echo "CONFIG_VHOST_USER=y" >> $config_host_mak
fi
+if test "$awd" = "yes" ; then
+ echo "CONFIG_AWD=y" >> $config_host_mak
+fi
if test "$vhost_user_fs" = "yes" ; then
echo "CONFIG_VHOST_USER_FS=y" >> $config_host_mak
fi
@@ -19,6 +19,7 @@ common-obj-y += colo-compare.o
common-obj-y += colo.o
common-obj-y += filter-rewriter.o
common-obj-y += filter-replay.o
+common-obj-$(CONFIG_AWD) += awd.o
tap-obj-$(CONFIG_LINUX) = tap-linux.o
tap-obj-$(CONFIG_BSD) = tap-bsd.o
new file mode 100644
@@ -0,0 +1,261 @@
+/*
+ * Advanced Watch Dog
+ *
+ * COarse-grain LOck-stepping Virtual Machines for Non-stop Service (COLO)
+ * (a.k.a. Fault Tolerance or Continuous Replication)
+ *
+ * Copyright (c) 2019 Intel Corporation
+ *
+ * Author: Zhang Chen <chen.zhang@intel.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * later. See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/error-report.h"
+#include "trace.h"
+#include "qemu-common.h"
+#include "qapi/error.h"
+#include "net/net.h"
+#include "qom/object_interfaces.h"
+#include "qom/object.h"
+#include "chardev/char-fe.h"
+#include "qemu/sockets.h"
+#include "sysemu/iothread.h"
+
+#define TYPE_AWD "advanced-watchdog"
+#define AWD(obj) OBJECT_CHECK(AwdState, (obj), TYPE_AWD)
+
+#define AWD_READ_LEN_MAX NET_BUFSIZE
+/* Default advanced watchdog pulse interval */
+#define AWD_PULSE_INTERVAL_DEFAULT 5000
+/* Default advanced watchdog timeout */
+#define AWD_TIMEOUT_DEFAULT 2000
+
+typedef struct AwdState {
+ Object parent;
+
+ bool server;
+ char *awd_node;
+ char *notification_node;
+ char *opt_script;
+ uint32_t pulse_interval;
+ uint32_t timeout;
+ IOThread *iothread;
+} AwdState;
+
+typedef struct AwdClass {
+ ObjectClass parent_class;
+} AwdClass;
+
+static char *awd_get_node(Object *obj, Error **errp)
+{
+ AwdState *s = AWD(obj);
+
+ return g_strdup(s->awd_node);
+}
+
+static void awd_set_node(Object *obj, const char *value, Error **errp)
+{
+ AwdState *s = AWD(obj);
+
+ g_free(s->awd_node);
+ s->awd_node = g_strdup(value);
+}
+
+static char *noti_get_node(Object *obj, Error **errp)
+{
+ AwdState *s = AWD(obj);
+
+ return g_strdup(s->notification_node);
+}
+
+static void noti_set_node(Object *obj, const char *value, Error **errp)
+{
+ AwdState *s = AWD(obj);
+
+ g_free(s->notification_node);
+ s->notification_node = g_strdup(value);
+}
+
+static char *opt_script_get_node(Object *obj, Error **errp)
+{
+ AwdState *s = AWD(obj);
+
+ return g_strdup(s->opt_script);
+}
+
+static void opt_script_set_node(Object *obj, const char *value, Error **errp)
+{
+ AwdState *s = AWD(obj);
+
+ g_free(s->opt_script);
+ s->opt_script = g_strdup(value);
+}
+
+static bool awd_get_server(Object *obj, Error **errp)
+{
+ AwdState *s = AWD(obj);
+
+ return s->server;
+}
+
+static void awd_set_server(Object *obj, bool value, Error **errp)
+{
+ AwdState *s = AWD(obj);
+
+ s->server = value;
+}
+
+static void awd_get_interval(Object *obj, Visitor *v,
+ const char *name, void *opaque,
+ Error **errp)
+{
+ AwdState *s = AWD(obj);
+ uint32_t value = s->pulse_interval;
+
+ visit_type_uint32(v, name, &value, errp);
+}
+
+static void awd_set_interval(Object *obj, Visitor *v,
+ const char *name, void *opaque,
+ Error **errp)
+{
+ AwdState *s = AWD(obj);
+ Error *local_err = NULL;
+ uint32_t value;
+
+ visit_type_uint32(v, name, &value, &local_err);
+ if (local_err) {
+ goto out;
+ }
+ if (!value) {
+ error_setg(&local_err, "Property '%s.%s' requires a positive value",
+ object_get_typename(obj), name);
+ goto out;
+ }
+ s->pulse_interval = value;
+
+out:
+ error_propagate(errp, local_err);
+}
+
+static void awd_get_timeout(Object *obj, Visitor *v,
+ const char *name, void *opaque,
+ Error **errp)
+{
+ AwdState *s = AWD(obj);
+ uint32_t value = s->timeout;
+
+ visit_type_uint32(v, name, &value, errp);
+}
+
+static void awd_set_timeout(Object *obj, Visitor *v,
+ const char *name, void *opaque,
+ Error **errp)
+{
+ AwdState *s = AWD(obj);
+ Error *local_err = NULL;
+ uint32_t value;
+
+ visit_type_uint32(v, name, &value, &local_err);
+ if (local_err) {
+ goto out;
+ }
+
+ if (!value) {
+ error_setg(&local_err, "Property '%s.%s' requires a positive value",
+ object_get_typename(obj), name);
+ goto out;
+ }
+ s->timeout = value;
+
+out:
+ error_propagate(errp, local_err);
+}
+
+static void awd_complete(UserCreatable *uc, Error **errp)
+{
+ AwdState *s = AWD(uc);
+
+ if (!s->awd_node || !s->iothread ||
+ !s->notification_node || !s->opt_script) {
+ error_setg(errp, "advanced-watchdog needs 'awd_node', "
+ "'notification_node', 'opt_script' "
+ "and 'server' property set");
+ return;
+ }
+
+ return;
+}
+
+static void awd_class_init(ObjectClass *oc, void *data)
+{
+ UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
+
+ ucc->complete = awd_complete;
+}
+
+static void awd_init(Object *obj)
+{
+ AwdState *s = AWD(obj);
+
+ object_property_add_str(obj, "awd_node",
+ awd_get_node, awd_set_node,
+ NULL);
+
+ object_property_add_str(obj, "notification_node",
+ noti_get_node, noti_set_node,
+ NULL);
+
+ object_property_add_str(obj, "opt_script",
+ opt_script_get_node, opt_script_set_node,
+ NULL);
+
+ object_property_add_bool(obj, "server",
+ awd_get_server,
+ awd_set_server, NULL);
+
+ object_property_add(obj, "pulse_interval", "uint32",
+ awd_get_interval,
+ awd_set_interval, NULL, NULL, NULL);
+
+ object_property_add(obj, "timeout", "uint32",
+ awd_get_timeout,
+ awd_set_timeout, NULL, NULL, NULL);
+
+ object_property_add_link(obj, "iothread", TYPE_IOTHREAD,
+ (Object **)&s->iothread,
+ object_property_allow_set_link,
+ OBJ_PROP_LINK_STRONG, NULL);
+}
+
+static void awd_finalize(Object *obj)
+{
+ AwdState *s = AWD(obj);
+
+ g_free(s->awd_node);
+ g_free(s->notification_node);
+}
+
+static const TypeInfo awd_info = {
+ .name = TYPE_AWD,
+ .parent = TYPE_OBJECT,
+ .instance_size = sizeof(AwdState),
+ .instance_init = awd_init,
+ .instance_finalize = awd_finalize,
+ .class_size = sizeof(AwdClass),
+ .class_init = awd_class_init,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_USER_CREATABLE },
+ { }
+ }
+};
+
+static void register_types(void)
+{
+ type_register_static(&awd_info);
+}
+
+type_init(register_types);
@@ -4572,6 +4572,12 @@ Dump the network traffic on netdev @var{dev} to the file specified by
The file format is libpcap, so it can be analyzed with tools such as tcpdump
or Wireshark.
+@item -object advanced-watchdog,id=@var{id},awd_node=@var{chardevid},notification_node=@var{chardevid},server=@var{server},iothread=@var{id}[,pulse_interval=@var{time_ms},timeout=@var{time_ms}]
+
+Advanced Watch Dog is an universal monitoring module on VMM side, it can be used to detect network down(VMM to guest, VMM to VMM, VMM to another remote server) and do previously set operation.
+for example: send message to admin, notify another VMM, send qmp command to qemu do some operation like restart the VM, build VMM heartbeat system, etc.
+It make user have basic VM/Host network monitoring tools and basic false tolerance and recovery solution.
+
@item -object colo-compare,id=@var{id},primary_in=@var{chardevid},secondary_in=@var{chardevid},outdev=@var{chardevid},iothread=@var{id}[,vnet_hdr_support][,notify_dev=@var{id}]
Colo-compare gets packet from primary_in@var{chardevid} and secondary_in@var{chardevid}, than compare primary packet with