@@ -383,6 +383,7 @@ vhost_scsi=""
vhost_vsock=""
vhost_user=""
vhost_user_fs=""
+awd="no"
kvm="no"
hax="no"
hvf="no"
@@ -1304,6 +1305,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"
@@ -1780,6 +1785,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
@@ -7043,6 +7049,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);
@@ -4589,6 +4589,26 @@ 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},opt_script=@var{path}[,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. AWD(Advanced WatchDog) use awd_node
+@var{chardevid} parameter to connect with a -chardev node for heartbeat
+service, and the service use the server @var{server} parameter to divided into
+server side and client side. The iothread @var{id} parameter make AWD attach to
+iothread and run independently of the main loop. The pulse_interval @var{time_ms}
+and timeout @var{time_ms} are heartbeat service property, default property are
+pulse_interval=5000, timeout=2000. AWD use the notification_node @var{chardevid}
+attach another -chardev socket node to do previously set operation, user can
+setup the operation(user command) in opt_script file, AWD will open this script
+and send it to notification_node. It make user have basic VM/Host network
+monitoring tools and basic false tolerance and recovery solution.
+
+Usage cases:
+Send message to admin, notify another VMM, send qmp command to qemu do some
+operation like restart the VM, build VMM heartbeat system, etc.
+
@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