فهرست منبع

qnetd: Add dead peer (client) detection

Signed-off-by: Jan Friesse <jfriesse@redhat.com>
Jan Friesse 10 سال پیش
والد
کامیت
5cc52fe3cb

+ 1 - 1
qdevices/Makefile.am

@@ -46,7 +46,7 @@ corosync_qnetd_SOURCES	= corosync-qnetd.c dynar.c msg.c msgio.c nss-sock.c  \
 			    qnetd-algo-ffsplit.c qnetd-cluster-list.c qnetd-client-send.c \
 			    qnetd-algo-2nodelms.c qnetd-algo-lms.c utils.c qnetd-instance.c \
 			    qnetd-client-net.c qnetd-client-msg-received.c qnetd-log-debug.c \
-			    qnetd-client-algo-timer.c
+			    qnetd-client-algo-timer.c qnetd-dpd-timer.c
 
 corosync_qdevice_SOURCES	= corosync-qdevice.c qdevice-cmap.c qdevice-instance.c node-list.c \
 				  utils.c qdevice-log.c qdevice-log-debug.c qdevice-votequorum.c \

+ 1 - 1
qdevices/qdevice-model-net.c

@@ -236,7 +236,7 @@ qdevice_model_net_run(struct qdevice_instance *instance)
 			/*
 			 * Give qnetd server a little time before reconnect
 			 */
-			poll(NULL, 0, random() % 1000);
+			(void)poll(NULL, 0, random() % 1000);
 		}
 	}
 

+ 3 - 0
qdevices/qnet-config.h

@@ -63,6 +63,9 @@ extern "C" {
 #define QNETD_HEARTBEAT_INTERVAL_MIN		(1*1000)
 #define QNETD_HEARTBEAT_INTERVAL_MAX		(2*60*1000)
 
+#define QNETD_DPD_ENABLED			1
+#define QNETD_DPD_INTERVAL			(10*1000)
+
 #define QNETD_LOCK_FILE				LOCALSTATEDIR"/run/corosync-qnetd.pid"
 
 #define QDEVICE_NET_NSS_DB_DIR			COROSYSCONFDIR "/qdevice/net/node/nssdb"

+ 2 - 0
qdevices/qnetd-client-msg-received.c

@@ -979,6 +979,8 @@ qnetd_client_msg_received(struct qnetd_instance *instance, struct qnetd_client *
 	int res;
 	int ret_val;
 
+	client->dpd_msg_received_since_last_check = 1;
+
 	msg_decoded_init(&msg);
 
 	res = msg_decode(&client->receive_buffer, &msg);

+ 2 - 0
qdevices/qnetd-client.h

@@ -80,6 +80,8 @@ struct qnetd_client {
 	struct timer_list_entry *algo_timer;
 	uint32_t algo_timer_vote_info_msq_seq_number;
 	int schedule_disconnect;
+	uint32_t dpd_time_since_last_check;
+	uint32_t dpd_msg_received_since_last_check;
 	TAILQ_ENTRY(qnetd_client) entries;
 	TAILQ_ENTRY(qnetd_client) cluster_entries;
 };

+ 97 - 0
qdevices/qnetd-dpd-timer.c

@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2015-2016 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Jan Friesse (jfriesse@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the Red Hat, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "qnetd-dpd-timer.h"
+#include "qnetd-log.h"
+
+static int
+qnetd_dpd_timer_cb(void *data1, void *data2)
+{
+	struct qnetd_instance *instance;
+	struct qnetd_client *client;
+
+	instance = (struct qnetd_instance *)data1;
+
+	TAILQ_FOREACH(client, &instance->clients, entries) {
+		if (!client->init_received) {
+			continue ;
+		}
+
+		client->dpd_time_since_last_check += QNETD_DPD_INTERVAL;
+
+		if (client->dpd_time_since_last_check > (client->heartbeat_interval * 2)) {
+			if (!client->dpd_msg_received_since_last_check) {
+				qnetd_log(LOG_WARNING, "Client %p doesn't sent any message during "
+				    "%"PRIu32"ms. Disconnecting",
+				    client, client->dpd_time_since_last_check);
+
+				client->schedule_disconnect = 1;
+			} else {
+				client->dpd_time_since_last_check = 0;
+				client->dpd_msg_received_since_last_check = 0;
+			}
+		}
+	}
+
+	return (-1);
+}
+
+int
+qnetd_dpd_timer_init(struct qnetd_instance *instance)
+{
+
+	if (!QNETD_DPD_ENABLED) {
+		return (0);
+	}
+
+	instance->dpd_timer = timer_list_add(&instance->main_timer_list, QNETD_DPD_INTERVAL,
+	    qnetd_dpd_timer_cb, (void *)instance, NULL);
+	if (instance->dpd_timer == NULL) {
+		qnetd_log(LOG_ERR, "Can't initialize dpd timer");
+
+		return (-1);
+	}
+
+	return (0);
+}
+
+void
+qnetd_dpd_timer_destroy(struct qnetd_instance *instance)
+{
+
+	if (instance->dpd_timer != NULL) {
+		timer_list_delete(&instance->main_timer_list, instance->dpd_timer);
+		instance->dpd_timer = NULL;
+	}
+}

+ 52 - 0
qdevices/qnetd-dpd-timer.h

@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015-2016 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Jan Friesse (jfriesse@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the Red Hat, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _QNETD_DPD_TIMER_H_
+#define _QNETD_DPD_TIMER_H_
+
+#include "qnetd-instance.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int		qnetd_dpd_timer_init(struct qnetd_instance *instance);
+
+extern void		qnetd_dpd_timer_destroy(struct qnetd_instance *instance);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _QNETD_DPD_TIMER_H_ */

+ 7 - 0
qdevices/qnetd-instance.c

@@ -39,6 +39,7 @@
 #include "qnetd-client.h"
 #include "qnetd-algorithm.h"
 #include "qnetd-log-debug.h"
+#include "qnetd-dpd-timer.h"
 
 int
 qnetd_instance_init(struct qnetd_instance *instance, size_t max_client_receive_size,
@@ -63,6 +64,10 @@ qnetd_instance_init(struct qnetd_instance *instance, size_t max_client_receive_s
 
 	timer_list_init(&instance->main_timer_list);
 
+	if (qnetd_dpd_timer_init(instance) != 0) {
+		return (0);
+	}
+
 	return (0);
 }
 
@@ -73,6 +78,8 @@ qnetd_instance_destroy(struct qnetd_instance *instance)
 	struct qnetd_client *client_next;
 
 
+	qnetd_dpd_timer_destroy(instance);
+
 	client = TAILQ_FIRST(&instance->clients);
 	while (client != NULL) {
 		client_next = TAILQ_NEXT(client, entries);

+ 1 - 0
qdevices/qnetd-instance.h

@@ -69,6 +69,7 @@ struct qnetd_instance {
 	const char *host_addr;
 	uint16_t host_port;
 	struct timer_list main_timer_list;
+	struct timer_list_entry *dpd_timer;		/* Dead peer detection timer */
 };
 
 extern int		qnetd_instance_init(struct qnetd_instance *instance,