Blame SOURCES/bz1678480-implment-checker-comparison.patch

b6983f
From fce93460597d27a86798c57ec410f63e4bd33be9 Mon Sep 17 00:00:00 2001
b6983f
From: YAMAMOTO Masaya <pandax381@gmail.com>
b6983f
Date: Fri, 7 Jul 2017 19:27:16 +0900
b6983f
Subject: [PATCH 3/8] Implement comparison of checkers
b6983f
b6983f
---
b6983f
 keepalived/check/check_api.c    | 29 ++++++++++++++++++++++++-
b6983f
 keepalived/check/check_daemon.c |  7 +++++-
b6983f
 keepalived/check/check_dns.c    | 24 +++++++++++++++++++--
b6983f
 keepalived/check/check_http.c   | 35 +++++++++++++++++++++++++++++-
b6983f
 keepalived/check/check_misc.c   | 22 ++++++++++++++++++-
b6983f
 keepalived/check/check_smtp.c   | 33 +++++++++++++++++++++++++++-
b6983f
 keepalived/check/check_tcp.c    | 22 +++++++++++++++++--
b6983f
 keepalived/check/ipwrapper.c    | 38 +++++++++++++++++++++++++--------
b6983f
 keepalived/include/check_api.h  |  5 +++++
b6983f
 9 files changed, 197 insertions(+), 18 deletions(-)
b6983f
b6983f
diff --git a/keepalived/check/check_api.c b/keepalived/check/check_api.c
b6983f
index b7081fd0..a722fc84 100644
b6983f
--- a/keepalived/check/check_api.c
b6983f
+++ b/keepalived/check/check_api.c
b6983f
@@ -42,8 +42,9 @@
b6983f
 #include "check_dns.h"
b6983f
 
b6983f
 /* Global vars */
b6983f
-static checker_id_t ncheckers = 0;
b6983f
+checker_id_t ncheckers = 0;
b6983f
 list checkers_queue;
b6983f
+list old_checkers_queue;
b6983f
 
b6983f
 /* free checker data */
b6983f
 static void
b6983f
@@ -80,6 +81,7 @@ dump_conn_opts(void *data)
b6983f
 void
b6983f
 queue_checker(void (*free_func) (void *), void (*dump_func) (void *)
b6983f
 	      , int (*launch) (thread_t *)
b6983f
+	      , int (*compare) (void *, void *)
b6983f
 	      , void *data
b6983f
 	      , conn_opts_t *co)
b6983f
 {
b6983f
@@ -96,6 +98,7 @@ queue_checker(void (*free_func) (void *), void (*dump_func) (void *)
b6983f
 	checker->free_func = free_func;
b6983f
 	checker->dump_func = dump_func;
b6983f
 	checker->launch = launch;
b6983f
+	checker->compare = compare;
b6983f
 	checker->vs = vs;
b6983f
 	checker->rs = rs;
b6983f
 	checker->data = data;
b6983f
@@ -117,6 +120,30 @@ queue_checker(void (*free_func) (void *), void (*dump_func) (void *)
b6983f
 	}
b6983f
 }
b6983f
 
b6983f
+int
b6983f
+compare_conn_opts(conn_opts_t *a, conn_opts_t *b)
b6983f
+{
b6983f
+	if (a == b)
b6983f
+		return 0;
b6983f
+
b6983f
+	if (!a || !b)
b6983f
+		goto err;
b6983f
+	if (!sockstorage_equal(&a->dst, &b->dst))
b6983f
+		goto err;
b6983f
+	if (!sockstorage_equal(&a->bindto, &b->bindto))
b6983f
+		goto err;
b6983f
+	//if (a->connection_to != b->connection_to)
b6983f
+	//	goto err;
b6983f
+#ifdef _WITH_SO_MARK_
b6983f
+	if (a->fwmark != b->fwmark)
b6983f
+		goto err;
b6983f
+#endif
b6983f
+
b6983f
+	return  0;
b6983f
+err:
b6983f
+	return -1;
b6983f
+}
b6983f
+
b6983f
 static void
b6983f
 checker_set_dst_port(struct sockaddr_storage *dst, uint16_t port)
b6983f
 {
b6983f
diff --git a/keepalived/check/check_daemon.c b/keepalived/check/check_daemon.c
b6983f
index a3ff8cab..462360e6 100644
b6983f
--- a/keepalived/check/check_daemon.c
b6983f
+++ b/keepalived/check/check_daemon.c
b6983f
@@ -233,7 +233,11 @@ reload_check_thread(__attribute__((unused)) thread_t * thread)
b6983f
 	thread_cleanup_master(master);
b6983f
 	free_global_data(global_data);
b6983f
 
b6983f
-	free_checkers_queue();
b6983f
+	/* Save previous checker data */
b6983f
+	old_checkers_queue = checkers_queue;
b6983f
+	checkers_queue = NULL;
b6983f
+	ncheckers = 0;
b6983f
+
b6983f
 	free_ssl();
b6983f
 	ipvs_stop();
b6983f
 
b6983f
@@ -246,6 +250,7 @@ reload_check_thread(__attribute__((unused)) thread_t * thread)
b6983f
 
b6983f
 	/* free backup data */
b6983f
 	free_check_data(old_check_data);
b6983f
+	free_list(&old_checkers_queue);
b6983f
 	UNSET_RELOAD;
b6983f
 
b6983f
 	return 0;
b6983f
diff --git a/keepalived/check/check_dns.c b/keepalived/check/check_dns.c
b6983f
index 96328027..84a5f56d 100644
b6983f
--- a/keepalived/check/check_dns.c
b6983f
+++ b/keepalived/check/check_dns.c
b6983f
@@ -388,6 +388,26 @@ dns_dump(void *data)
b6983f
 	log_message(LOG_INFO, "   Name = %s", dns_check->name);
b6983f
 }
b6983f
 
b6983f
+static int
b6983f
+dns_compare(void *a, void *b)
b6983f
+{
b6983f
+	dns_check_t *old = CHECKER_DATA(a);
b6983f
+	dns_check_t *new = CHECKER_DATA(b);
b6983f
+
b6983f
+	if (compare_conn_opts(CHECKER_CO(a), CHECKER_CO(b)) != 0)
b6983f
+		goto err;
b6983f
+	if (old->retry != new->retry)
b6983f
+		goto err;
b6983f
+	if (strcmp(old->type, new->type) != 0)
b6983f
+		goto err;
b6983f
+	if (strcmp(old->name, new->name) != 0)
b6983f
+		goto err;
b6983f
+
b6983f
+	return  0;
b6983f
+err:
b6983f
+	return -1;
b6983f
+}
b6983f
+
b6983f
 static void
b6983f
 dns_check_handler(__attribute__((unused)) vector_t * strvec)
b6983f
 {
b6983f
@@ -396,8 +416,8 @@ dns_check_handler(__attribute__((unused)) vector_t * strvec)
b6983f
 	dns_check->attempts = 0;
b6983f
 	dns_check->type = DNS_DEFAULT_TYPE;
b6983f
 	dns_check->name = DNS_DEFAULT_NAME;
b6983f
-	queue_checker(dns_free, dns_dump, dns_connect_thread, dns_check,
b6983f
-		      CHECKER_NEW_CO());
b6983f
+	queue_checker(dns_free, dns_dump, dns_connect_thread,
b6983f
+		      dns_compare, dns_check, CHECKER_NEW_CO());
b6983f
 }
b6983f
 
b6983f
 static void
b6983f
diff --git a/keepalived/check/check_http.c b/keepalived/check/check_http.c
b6983f
index 05e29b23..c2089a3b 100644
b6983f
--- a/keepalived/check/check_http.c
b6983f
+++ b/keepalived/check/check_http.c
b6983f
@@ -123,6 +123,38 @@ alloc_http_get(char *proto)
b6983f
 	return http_get_chk;
b6983f
 }
b6983f
 
b6983f
+static int
b6983f
+compare_http_get_check(void *a, void *b)
b6983f
+{
b6983f
+	http_checker_t *old = CHECKER_DATA(a);
b6983f
+	http_checker_t *new = CHECKER_DATA(b);
b6983f
+	size_t n;
b6983f
+	url_t *u1, *u2;
b6983f
+
b6983f
+	if (compare_conn_opts(CHECKER_CO(a), CHECKER_CO(b)) != 0)
b6983f
+		goto err;
b6983f
+	if (old->nb_get_retry != new->nb_get_retry)
b6983f
+		goto err;
b6983f
+	if (old->delay_before_retry != new->delay_before_retry)
b6983f
+		goto err;
b6983f
+	if (LIST_SIZE(old->url) != LIST_SIZE(new->url))
b6983f
+		goto err;
b6983f
+	for (n = 0; n < LIST_SIZE(new->url); n++) {
b6983f
+		u1 = (url_t *)list_element(old->url, n);
b6983f
+		u2 = (url_t *)list_element(new->url, n);
b6983f
+		if (strcmp(u1->path, u2->path) != 0)
b6983f
+			goto err;
b6983f
+		if (strcmp(u1->digest, u2->digest) != 0)
b6983f
+			goto err;
b6983f
+		if (u1->status_code != u2->status_code)
b6983f
+			goto err;
b6983f
+	}
b6983f
+
b6983f
+	return  0;
b6983f
+err:
b6983f
+	return -1;
b6983f
+}
b6983f
+
b6983f
 static void
b6983f
 http_get_handler(vector_t *strvec)
b6983f
 {
b6983f
@@ -132,7 +164,8 @@ http_get_handler(vector_t *strvec)
b6983f
 	/* queue new checker */
b6983f
 	http_get_chk = alloc_http_get(str);
b6983f
 	queue_checker(free_http_get_check, dump_http_get_check,
b6983f
-		      http_connect_thread, http_get_chk, CHECKER_NEW_CO());
b6983f
+		      http_connect_thread, compare_http_get_check,
b6983f
+		      http_get_chk, CHECKER_NEW_CO());
b6983f
 }
b6983f
 
b6983f
 static void
b6983f
diff --git a/keepalived/check/check_misc.c b/keepalived/check/check_misc.c
b6983f
index 10ac1e23..311a1127 100644
b6983f
--- a/keepalived/check/check_misc.c
b6983f
+++ b/keepalived/check/check_misc.c
b6983f
@@ -72,6 +72,26 @@ dump_misc_check(void *data)
b6983f
 	log_message(LOG_INFO, "   insecure = %s", misck_checker->insecure ? "Yes" : "No");
b6983f
 }
b6983f
 
b6983f
+static int
b6983f
+compare_misc_check(void *a, void *b)
b6983f
+{
b6983f
+	misc_checker_t *old = CHECKER_DATA(a);
b6983f
+	misc_checker_t *new = CHECKER_DATA(b);
b6983f
+
b6983f
+	if (strcmp(old->path, new->path) != 0)
b6983f
+		goto err;
b6983f
+	if (old->timeout != new->timeout)
b6983f
+		goto err;
b6983f
+	if (old->dynamic != new->dynamic)
b6983f
+		goto err;
b6983f
+	if (old->uid != new->uid || new->gid != new->gid)
b6983f
+		goto err;
b6983f
+
b6983f
+	return  0;
b6983f
+err:
b6983f
+	return -1;
b6983f
+}
b6983f
+
b6983f
 static void
b6983f
 misc_check_handler(__attribute__((unused)) vector_t *strvec)
b6983f
 {
b6983f
@@ -149,7 +169,7 @@ log_message(LOG_INFO, "Setting uid.gid");
b6983f
 	}
b6983f
 
b6983f
 	/* queue new checker */
b6983f
-	queue_checker(free_misc_check, dump_misc_check, misc_check_thread, misck_checker, NULL);
b6983f
+	queue_checker(free_misc_check, dump_misc_check, misc_check_thread, compare_misc_check, misck_checker, NULL);
b6983f
 	misck_checker = NULL;
b6983f
 log_message(LOG_INFO, "Leaving misc_end_handler");
b6983f
 }
b6983f
diff --git a/keepalived/check/check_smtp.c b/keepalived/check/check_smtp.c
b6983f
index 901b77f5..e19511cc 100644
b6983f
--- a/keepalived/check/check_smtp.c
b6983f
+++ b/keepalived/check/check_smtp.c
b6983f
@@ -82,6 +82,37 @@ dump_smtp_check(void *data)
b6983f
 	dump_list(smtp_checker->host);
b6983f
 }
b6983f
 
b6983f
+static int
b6983f
+compare_smtp_check(void *a, void *b)
b6983f
+{
b6983f
+	smtp_checker_t *old = CHECKER_DATA(a);
b6983f
+	smtp_checker_t *new = CHECKER_DATA(b);
b6983f
+	size_t n;
b6983f
+	smtp_host_t *h1, *h2;
b6983f
+
b6983f
+	if (strcmp(old->helo_name, new->helo_name) != 0)
b6983f
+		goto err;
b6983f
+	if (old->retry != new->retry)
b6983f
+		goto err;
b6983f
+	if (old->db_retry != new->db_retry)
b6983f
+		goto err;
b6983f
+	if (compare_conn_opts(CHECKER_CO(a), CHECKER_CO(b)) != 0)
b6983f
+		goto err;
b6983f
+	if (LIST_SIZE(old->host) != LIST_SIZE(new->host))
b6983f
+		goto err;
b6983f
+	for (n = 0; n < LIST_SIZE(new->host); n++) {
b6983f
+		h1 = (smtp_host_t *)list_element(old->host, n);
b6983f
+		h2 = (smtp_host_t *)list_element(new->host, n);
b6983f
+		if (compare_conn_opts(h1, h2) != 0) {
b6983f
+			goto err;
b6983f
+		}
b6983f
+	}
b6983f
+
b6983f
+	return  0;
b6983f
+err:
b6983f
+	return -1;
b6983f
+}
b6983f
+
b6983f
 /* Allocates a default host structure */
b6983f
 static smtp_host_t *
b6983f
 smtp_alloc_host(void)
b6983f
@@ -136,7 +167,7 @@ smtp_check_handler(__attribute__((unused)) vector_t *strvec)
b6983f
 	 *               void *data, conn_opts_t *)
b6983f
 	 */
b6983f
 	queue_checker(free_smtp_check, dump_smtp_check, smtp_connect_thread,
b6983f
-		      smtp_checker, smtp_checker->default_co);
b6983f
+		      compare_smtp_check, smtp_checker, smtp_checker->default_co);
b6983f
 
b6983f
 	/*
b6983f
 	 * Last, allocate the list that will hold all the per host
b6983f
diff --git a/keepalived/check/check_tcp.c b/keepalived/check/check_tcp.c
b6983f
index 078ba705..026a0e3c 100644
b6983f
--- a/keepalived/check/check_tcp.c
b6983f
+++ b/keepalived/check/check_tcp.c
b6983f
@@ -62,6 +62,24 @@ dump_tcp_check(void *data)
b6983f
 	}
b6983f
 }
b6983f
 
b6983f
+static int
b6983f
+compare_tcp_check(void *a, void *b)
b6983f
+{
b6983f
+	tcp_check_t *old = CHECKER_DATA(a);
b6983f
+	tcp_check_t *new = CHECKER_DATA(b);
b6983f
+
b6983f
+	if (compare_conn_opts(CHECKER_CO(a), CHECKER_CO(b)) != 0)
b6983f
+		goto err;
b6983f
+	if (old->n_retry != new->n_retry)
b6983f
+		goto err;
b6983f
+	if (old->delay_before_retry != new->delay_before_retry)
b6983f
+		goto err;
b6983f
+
b6983f
+	return  0;
b6983f
+err:
b6983f
+	return -1;
b6983f
+}
b6983f
+
b6983f
 static void
b6983f
 tcp_check_handler(__attribute__((unused)) vector_t *strvec)
b6983f
 {
b6983f
@@ -72,8 +90,8 @@ tcp_check_handler(__attribute__((unused)) vector_t *strvec)
b6983f
 	tcp_check->delay_before_retry = 1 * TIMER_HZ;
b6983f
 
b6983f
 	/* queue new checker */
b6983f
-	queue_checker(free_tcp_check, dump_tcp_check, tcp_connect_thread
b6983f
-		      ,tcp_check, CHECKER_NEW_CO());
b6983f
+	queue_checker(free_tcp_check, dump_tcp_check, tcp_connect_thread,
b6983f
+		      compare_tcp_check, tcp_check, CHECKER_NEW_CO());
b6983f
 }
b6983f
 
b6983f
 static void
b6983f
diff --git a/keepalived/check/ipwrapper.c b/keepalived/check/ipwrapper.c
b6983f
index 6acf18ba..49262e25 100644
b6983f
--- a/keepalived/check/ipwrapper.c
b6983f
+++ b/keepalived/check/ipwrapper.c
b6983f
@@ -626,20 +626,40 @@ rs_exist(real_server_t * old_rs, list l)
b6983f
 static void
b6983f
 migrate_failed_checkers(real_server_t *old_rs, real_server_t *new_rs)
b6983f
 {
b6983f
-	element e;
b6983f
-	checker_t *checker;
b6983f
+	list l;
b6983f
+	element e, e1;
b6983f
+	checker_t *old_c, *new_c;
b6983f
 	checker_id_t *id;
b6983f
 
b6983f
-	/* Notes: It's a provisional implementation */
b6983f
-	(void)old_rs;
b6983f
+	l = alloc_list(NULL, NULL);
b6983f
+	for (e = LIST_HEAD(old_checkers_queue); e; ELEMENT_NEXT(e)) {
b6983f
+		old_c = ELEMENT_DATA(e);
b6983f
+		if (old_c->rs == old_rs) {
b6983f
+			list_add(l, old_c);
b6983f
+		}
b6983f
+	}
b6983f
+
b6983f
+	if (LIST_ISEMPTY(l))
b6983f
+		goto end;
b6983f
+
b6983f
 	for (e = LIST_HEAD(checkers_queue); e; ELEMENT_NEXT(e)) {
b6983f
-		checker = ELEMENT_DATA(e);
b6983f
-		if (checker->rs == new_rs) {
b6983f
-			id = (checker_id_t *) MALLOC(sizeof(checker_id_t));
b6983f
-			*id = checker->id;
b6983f
-			list_add(new_rs->failed_checkers, id);
b6983f
+		new_c = ELEMENT_DATA(e);
b6983f
+		if (new_c->rs != new_rs || !new_c->compare)
b6983f
+			continue;
b6983f
+		for (e1 = LIST_HEAD(l); e1; ELEMENT_NEXT(e1)) {
b6983f
+			old_c = ELEMENT_DATA(e1);
b6983f
+			if (old_c->compare == new_c->compare && new_c->compare(old_c, new_c) == 0) {
b6983f
+				if (svr_checker_up(old_c->id, old_rs) == 0) {
b6983f
+					id = (checker_id_t *) MALLOC(sizeof(checker_id_t));
b6983f
+					*id = old_c->id;
b6983f
+					list_add(new_rs->failed_checkers, id);
b6983f
+				}
b6983f
+				break;
b6983f
+			}
b6983f
 		}
b6983f
 	}
b6983f
+end:
b6983f
+	free_list(&l);
b6983f
 }
b6983f
 
b6983f
 /* Clear the diff rs of the old vs */
b6983f
diff --git a/keepalived/include/check_api.h b/keepalived/include/check_api.h
b6983f
index 359c794a..4a10a36b 100644
b6983f
--- a/keepalived/include/check_api.h
b6983f
+++ b/keepalived/include/check_api.h
b6983f
@@ -36,6 +36,7 @@ typedef struct _checker {
b6983f
 	void				(*free_func) (void *);
b6983f
 	void				(*dump_func) (void *);
b6983f
 	int				(*launch) (struct _thread *);
b6983f
+	int				(*compare) (void *, void *);
b6983f
 	virtual_server_t		*vs;	/* pointer to the checker thread virtualserver */
b6983f
 	real_server_t			*rs;	/* pointer to the checker thread realserver */
b6983f
 	void				*data;
b6983f
@@ -46,7 +47,9 @@ typedef struct _checker {
b6983f
 } checker_t;
b6983f
 
b6983f
 /* Checkers queue */
b6983f
+extern checker_id_t ncheckers;
b6983f
 extern list checkers_queue;
b6983f
+extern list old_checkers_queue;
b6983f
 
b6983f
 /* utility macro */
b6983f
 #define CHECKER_ARG(X) ((X)->data)
b6983f
@@ -68,8 +71,10 @@ extern void init_checkers_queue(void);
b6983f
 extern void dump_conn_opts(void *);
b6983f
 extern void queue_checker(void (*free_func) (void *), void (*dump_func) (void *)
b6983f
 			  , int (*launch) (thread_t *)
b6983f
+			  , int (*compare) (void *, void *)
b6983f
 			  , void *
b6983f
 			  , conn_opts_t *);
b6983f
+extern int  compare_conn_opts(conn_opts_t *, conn_opts_t *);
b6983f
 extern void dump_checkers_queue(void);
b6983f
 extern void free_checkers_queue(void);
b6983f
 extern void register_checkers_thread(void);
b6983f
-- 
b6983f
2.20.1
b6983f