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