From 1812d38cb85eb3766e1ed0adbf75b57475af6b0e Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Mon, 2 Jul 2018 12:30:08 +0100 Subject: [PATCH] [Feature] Distinguish IP failures from connection failures --- src/fuzzy_storage.c | 2 +- src/libserver/dns.c | 2 +- src/libserver/fuzzy_backend_redis.c | 18 +++++++++--------- src/libstat/backends/redis_backend.c | 11 ++++++----- src/libstat/learn_cache/redis_cache.c | 6 +++--- src/libutil/upstream.c | 12 +++++++----- src/libutil/upstream.h | 2 +- src/lua/lua_upstream.c | 8 +++++++- src/plugins/fuzzy_check.c | 14 +++++++------- src/plugins/surbl.c | 2 +- src/rspamd_proxy.c | 8 ++++---- test/rspamd_upstream_test.c | 4 ++-- 12 files changed, 49 insertions(+), 40 deletions(-) diff --git a/src/fuzzy_storage.c b/src/fuzzy_storage.c index 9243e369e..c97756aba 100644 --- a/src/fuzzy_storage.c +++ b/src/fuzzy_storage.c @@ -452,7 +452,7 @@ rspamd_fuzzy_send_update_mirror (struct rspamd_fuzzy_storage_ctx *ctx, if (conn->sock == -1) { msg_err ("cannot connect upstream for %s", m->name); - rspamd_upstream_fail (conn->up); + rspamd_upstream_fail (conn->up, TRUE); return; } diff --git a/src/libserver/dns.c b/src/libserver/dns.c index c07447471..b10eaf8c4 100644 --- a/src/libserver/dns.c +++ b/src/libserver/dns.c @@ -593,7 +593,7 @@ rspamd_dns_upstream_fail (struct rdns_upstream_elt *elt, { struct upstream *up = elt->lib_data; - rspamd_upstream_fail (up); + rspamd_upstream_fail (up, FALSE); } static unsigned int diff --git a/src/libserver/fuzzy_backend_redis.c b/src/libserver/fuzzy_backend_redis.c index 06f100132..d25f057ed 100644 --- a/src/libserver/fuzzy_backend_redis.c +++ b/src/libserver/fuzzy_backend_redis.c @@ -467,7 +467,7 @@ rspamd_fuzzy_redis_shingles_callback (redisAsyncContext *c, gpointer r, msg_err_redis_session ("error getting shingles: %s", c->errstr); } - rspamd_upstream_fail (session->up); + rspamd_upstream_fail (session->up, FALSE); } rspamd_fuzzy_redis_session_dtor (session, FALSE); @@ -606,7 +606,7 @@ rspamd_fuzzy_redis_check_callback (redisAsyncContext *c, gpointer r, msg_err_redis_session ("error getting hashes: %s", c->errstr); } - rspamd_upstream_fail (session->up); + rspamd_upstream_fail (session->up, FALSE); } rspamd_fuzzy_redis_session_dtor (session, FALSE); @@ -674,7 +674,7 @@ rspamd_fuzzy_backend_check_redis (struct rspamd_fuzzy_backend *bk, rspamd_inet_address_get_port (addr)); if (session->ctx == NULL) { - rspamd_upstream_fail (up); + rspamd_upstream_fail (up, TRUE); rspamd_fuzzy_redis_session_dtor (session, TRUE); if (cb) { @@ -744,7 +744,7 @@ rspamd_fuzzy_redis_count_callback (redisAsyncContext *c, gpointer r, msg_err_redis_session ("error getting count: %s", c->errstr); } - rspamd_upstream_fail (session->up); + rspamd_upstream_fail (session->up, FALSE); } rspamd_fuzzy_redis_session_dtor (session, FALSE); @@ -798,7 +798,7 @@ rspamd_fuzzy_backend_count_redis (struct rspamd_fuzzy_backend *bk, rspamd_inet_address_get_port (addr)); if (session->ctx == NULL) { - rspamd_upstream_fail (up); + rspamd_upstream_fail (up, TRUE); rspamd_fuzzy_redis_session_dtor (session, TRUE); if (cb) { @@ -866,7 +866,7 @@ rspamd_fuzzy_redis_version_callback (redisAsyncContext *c, gpointer r, msg_err_redis_session ("error getting version: %s", c->errstr); } - rspamd_upstream_fail (session->up); + rspamd_upstream_fail (session->up, FALSE); } rspamd_fuzzy_redis_session_dtor (session, FALSE); @@ -921,7 +921,7 @@ rspamd_fuzzy_backend_version_redis (struct rspamd_fuzzy_backend *bk, rspamd_inet_address_get_port (addr)); if (session->ctx == NULL) { - rspamd_upstream_fail (up); + rspamd_upstream_fail (up, FALSE); rspamd_fuzzy_redis_session_dtor (session, TRUE); if (cb) { @@ -1272,7 +1272,7 @@ rspamd_fuzzy_redis_update_callback (redisAsyncContext *c, gpointer r, msg_err_redis_session ("error sending update to redis: %s", c->errstr); } - rspamd_upstream_fail (session->up); + rspamd_upstream_fail (session->up, FALSE); } rspamd_fuzzy_redis_session_dtor (session, FALSE); @@ -1382,7 +1382,7 @@ rspamd_fuzzy_backend_update_redis (struct rspamd_fuzzy_backend *bk, rspamd_inet_address_get_port (addr)); if (session->ctx == NULL) { - rspamd_upstream_fail (up); + rspamd_upstream_fail (up, TRUE); rspamd_fuzzy_redis_session_dtor (session, TRUE); if (cb) { diff --git a/src/libstat/backends/redis_backend.c b/src/libstat/backends/redis_backend.c index 79fafd15b..0b421f2a5 100644 --- a/src/libstat/backends/redis_backend.c +++ b/src/libstat/backends/redis_backend.c @@ -909,7 +909,8 @@ rspamd_redis_stat_keys (redisAsyncContext *c, gpointer r, gpointer priv) else { msg_err ("cannot get keys to gather stat: unknown error"); } - rspamd_upstream_fail (cbdata->selected); + + rspamd_upstream_fail (cbdata->selected, FALSE); rspamd_redis_async_cbdata_cleanup (cbdata); } } @@ -1031,7 +1032,7 @@ rspamd_redis_timeout (gint fd, short what, gpointer d) msg_err_task_check ("connection to redis server %s timed out", rspamd_upstream_name (rt->selected)); - rspamd_upstream_fail (rt->selected); + rspamd_upstream_fail (rt->selected, FALSE); if (rt->redis) { redis = rt->redis; @@ -1091,7 +1092,7 @@ rspamd_redis_connected (redisAsyncContext *c, gpointer r, gpointer priv) else { msg_err_task ("error getting reply from redis server %s: %s", rspamd_upstream_name (rt->selected), c->errstr); - rspamd_upstream_fail (rt->selected); + rspamd_upstream_fail (rt->selected, FALSE); if (!rt->err) { g_set_error (&rt->err, rspamd_redis_stat_quark (), c->err, @@ -1178,7 +1179,7 @@ rspamd_redis_processed (redisAsyncContext *c, gpointer r, gpointer priv) rspamd_upstream_name (rt->selected), c->errstr); if (rt->redis) { - rspamd_upstream_fail (rt->selected); + rspamd_upstream_fail (rt->selected, FALSE); } if (!rt->err) { @@ -1210,7 +1211,7 @@ rspamd_redis_learned (redisAsyncContext *c, gpointer r, gpointer priv) rspamd_upstream_name (rt->selected), c->errstr); if (rt->redis) { - rspamd_upstream_fail (rt->selected); + rspamd_upstream_fail (rt->selected, FALSE); } if (!rt->err) { diff --git a/src/libstat/learn_cache/redis_cache.c b/src/libstat/learn_cache/redis_cache.c index c3f4c6598..d43ec3665 100644 --- a/src/libstat/learn_cache/redis_cache.c +++ b/src/libstat/learn_cache/redis_cache.c @@ -95,7 +95,7 @@ rspamd_redis_cache_timeout (gint fd, short what, gpointer d) msg_err_task ("connection to redis server %s timed out", rspamd_upstream_name (rt->selected)); - rspamd_upstream_fail (rt->selected); + rspamd_upstream_fail (rt->selected, FALSE); if (rt->has_event) { rspamd_session_remove_event (task->s, rspamd_redis_cache_fin, d); @@ -147,7 +147,7 @@ rspamd_stat_cache_redis_get (redisAsyncContext *c, gpointer r, gpointer priv) rspamd_upstream_ok (rt->selected); } else { - rspamd_upstream_fail (rt->selected); + rspamd_upstream_fail (rt->selected, FALSE); } if (rt->has_event) { @@ -169,7 +169,7 @@ rspamd_stat_cache_redis_set (redisAsyncContext *c, gpointer r, gpointer priv) rspamd_upstream_ok (rt->selected); } else { - rspamd_upstream_fail (rt->selected); + rspamd_upstream_fail (rt->selected, FALSE); } if (rt->has_event) { diff --git a/src/libutil/upstream.c b/src/libutil/upstream.c index 310a768ef..883c6f2eb 100644 --- a/src/libutil/upstream.c +++ b/src/libutil/upstream.c @@ -428,7 +428,7 @@ rspamd_upstream_set_inactive (struct upstream_list *ls, struct upstream *up) } void -rspamd_upstream_fail (struct upstream *up) +rspamd_upstream_fail (struct upstream *up, gboolean addr_failure) { gdouble error_rate, max_error_rate; gdouble sec_last, sec_cur; @@ -476,10 +476,12 @@ rspamd_upstream_fail (struct upstream *up) } } - /* Also increase count of errors for this specific address */ - if (up->addrs.addr) { - addr_elt = g_ptr_array_index (up->addrs.addr, up->addrs.cur); - addr_elt->errors ++; + if (addr_failure) { + /* Also increase count of errors for this specific address */ + if (up->addrs.addr) { + addr_elt = g_ptr_array_index (up->addrs.addr, up->addrs.cur); + addr_elt->errors++; + } } RSPAMD_UPSTREAM_UNLOCK (up->lock); diff --git a/src/libutil/upstream.h b/src/libutil/upstream.h index 84e75288d..3bc2132da 100644 --- a/src/libutil/upstream.h +++ b/src/libutil/upstream.h @@ -55,7 +55,7 @@ void rspamd_upstreams_library_config (struct rspamd_config *cfg, /** * Add an error to an upstream */ -void rspamd_upstream_fail (struct upstream *up); +void rspamd_upstream_fail (struct upstream *up, gboolean addr_failure); /** * Increase upstream successes count diff --git a/src/lua/lua_upstream.c b/src/lua/lua_upstream.c index e403d34af..0d1246229 100644 --- a/src/lua/lua_upstream.c +++ b/src/lua/lua_upstream.c @@ -124,9 +124,15 @@ static gint lua_upstream_fail (lua_State *L) { struct upstream *up = lua_check_upstream (L); + gboolean fail_addr = FALSE; if (up) { - rspamd_upstream_fail (up); + + if (lua_isboolean (L, 2)) { + fail_addr = lua_toboolean (L, 2); + } + + rspamd_upstream_fail (up, fail_addr); } return 0; diff --git a/src/plugins/fuzzy_check.c b/src/plugins/fuzzy_check.c index 777f6fa62..766d11e5f 100644 --- a/src/plugins/fuzzy_check.c +++ b/src/plugins/fuzzy_check.c @@ -2168,7 +2168,7 @@ fuzzy_check_io_callback (gint fd, short what, void *arg) session->state == 1 ? "read" : "write", errno, strerror (errno)); - rspamd_upstream_fail (session->server); + rspamd_upstream_fail (session->server, FALSE); rspamd_session_remove_event (session->task->s, fuzzy_io_fin, session); } else { @@ -2207,7 +2207,7 @@ fuzzy_check_timer_callback (gint fd, short what, void *arg) rspamd_upstream_name (session->server), rspamd_inet_address_to_string_pretty (session->addr), session->retransmits); - rspamd_upstream_fail (session->server); + rspamd_upstream_fail (session->server, FALSE); rspamd_session_remove_event (session->task->s, fuzzy_io_fin, session); } else { @@ -2412,7 +2412,7 @@ fuzzy_controller_io_callback (gint fd, short what, void *arg) rspamd_upstream_name (session->server), rspamd_inet_address_to_string_pretty (session->addr), errno, strerror (errno)); - rspamd_upstream_fail (session->server); + rspamd_upstream_fail (session->server, FALSE); } /* @@ -2509,7 +2509,7 @@ fuzzy_controller_timer_callback (gint fd, short what, void *arg) task = session->task; if (session->retransmits >= fuzzy_module_ctx->retransmits) { - rspamd_upstream_fail (session->server); + rspamd_upstream_fail (session->server, FALSE); msg_err_task_check ("got IO timeout with server %s(%s), " "after %d retransmits", rspamd_upstream_name (session->server), @@ -2831,7 +2831,7 @@ register_fuzzy_client_call (struct rspamd_task *task, rspamd_inet_address_to_string_pretty (addr), errno, strerror (errno)); - rspamd_upstream_fail (selected); + rspamd_upstream_fail (selected, FALSE); g_ptr_array_free (commands, TRUE); } else { @@ -2942,7 +2942,7 @@ register_fuzzy_controller_call (struct rspamd_http_connection_entry *entry, if ((sock = rspamd_inet_address_connect (addr, SOCK_DGRAM, TRUE)) == -1) { - rspamd_upstream_fail (selected); + rspamd_upstream_fail (selected, TRUE); } else { s = @@ -3302,7 +3302,7 @@ fuzzy_check_send_lua_learn (struct fuzzy_rule *rule, if ((sock = rspamd_inet_address_connect (addr, SOCK_DGRAM, TRUE)) == -1) { - rspamd_upstream_fail (selected); + rspamd_upstream_fail (selected, TRUE); } else { s = diff --git a/src/plugins/surbl.c b/src/plugins/surbl.c index 64b1b14f6..bfb6f4e82 100644 --- a/src/plugins/surbl.c +++ b/src/plugins/surbl.c @@ -1539,7 +1539,7 @@ surbl_redirector_error (struct rspamd_http_connection *conn, msg_err_surbl ("connection with http server %s terminated incorrectly: %e", rspamd_inet_address_to_string (rspamd_upstream_addr (param->redirector)), err); - rspamd_upstream_fail (param->redirector); + rspamd_upstream_fail (param->redirector, FALSE); rspamd_session_remove_event (param->task->s, free_redirector_session, param); } diff --git a/src/rspamd_proxy.c b/src/rspamd_proxy.c index 1d4324bdc..4af5ee5f4 100644 --- a/src/rspamd_proxy.c +++ b/src/rspamd_proxy.c @@ -1308,7 +1308,7 @@ proxy_backend_mirror_error_handler (struct rspamd_http_connection *conn, GError bk_conn->err = rspamd_mempool_strdup (session->pool, err->message); } - rspamd_upstream_fail (bk_conn->up); + rspamd_upstream_fail (bk_conn->up, FALSE); proxy_backend_close_connection (bk_conn); REF_RELEASE (bk_conn->s); @@ -1384,7 +1384,7 @@ proxy_open_mirror_connections (struct rspamd_proxy_session *session) if (bk_conn->backend_sock == -1) { msg_err_session ("cannot connect upstream for %s", m->name); - rspamd_upstream_fail (bk_conn->up); + rspamd_upstream_fail (bk_conn->up, TRUE); continue; } @@ -1505,7 +1505,7 @@ proxy_backend_master_error_handler (struct rspamd_http_connection *conn, GError err, session->ctx->max_retries - session->retries); session->retries ++; - rspamd_upstream_fail (bk_conn->up); + rspamd_upstream_fail (bk_conn->up, FALSE); proxy_backend_close_connection (session->master_conn); if (session->ctx->max_retries && @@ -1810,7 +1810,7 @@ retry: host ? hostbuf : "default", rspamd_inet_address_to_string (rspamd_upstream_addr ( session->master_conn->up))); - rspamd_upstream_fail (session->master_conn->up); + rspamd_upstream_fail (session->master_conn->up, TRUE); session->retries ++; goto retry; } diff --git a/test/rspamd_upstream_test.c b/test/rspamd_upstream_test.c index cce0008a9..4e4f1ae87 100644 --- a/test/rspamd_upstream_test.c +++ b/test/rspamd_upstream_test.c @@ -103,7 +103,7 @@ rspamd_upstream_test_func (void) next_addr = rspamd_upstream_addr (up); g_assert (rspamd_inet_address_get_af (next_addr) == AF_INET6); /* Test errors with IPv6 */ - rspamd_upstream_fail (up); + rspamd_upstream_fail (up, TRUE); /* Now we should have merely IPv4 addresses in rotation */ addr = rspamd_upstream_addr (up); for (i = 0; i < 256; i++) { @@ -166,7 +166,7 @@ rspamd_upstream_test_func (void) up = rspamd_upstream_get (ls, RSPAMD_UPSTREAM_MASTER_SLAVE, NULL, 0); for (i = 0; i < 100; i ++) { - rspamd_upstream_fail (up); + rspamd_upstream_fail (up, TRUE); } g_assert (rspamd_upstreams_alive (ls) == 2); -- 2.39.5