summaryrefslogtreecommitdiffstats
path: root/debian/patches/0013-daemon-more-avoidance-of-excessive-TCP-reconnections.patch
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--debian/patches/0013-daemon-more-avoidance-of-excessive-TCP-reconnections.patch153
1 files changed, 153 insertions, 0 deletions
diff --git a/debian/patches/0013-daemon-more-avoidance-of-excessive-TCP-reconnections.patch b/debian/patches/0013-daemon-more-avoidance-of-excessive-TCP-reconnections.patch
new file mode 100644
index 0000000..fb1a3e4
--- /dev/null
+++ b/debian/patches/0013-daemon-more-avoidance-of-excessive-TCP-reconnections.patch
@@ -0,0 +1,153 @@
+From: =?utf-8?b?VmxhZGltw61yIMSMdW7DoXQ=?= <vladimir.cunat@nic.cz>
+Date: Sat, 29 Jul 2023 17:53:34 +0200
+Subject: daemon: more avoidance of excessive TCP reconnections
+
+Previously this penalization was only triggered if the remote server
+closed TCP. Now it's extended to us closing it when the server
+(only) sends back some nonsense. At least for the cases which I could
+see immediately.
+
+That's just three trivial one-line additions; the rest is refactoring.
+---
+ daemon/io.c | 38 ++++++++++----------------------------
+ daemon/session.c | 26 +++++++++++++++++++++-----
+ daemon/session.h | 5 +++--
+ 3 files changed, 34 insertions(+), 35 deletions(-)
+
+diff --git a/daemon/io.c b/daemon/io.c
+index 48bfed3..ac0d969 100644
+--- a/daemon/io.c
++++ b/daemon/io.c
+@@ -337,33 +337,6 @@ void tcp_timeout_trigger(uv_timer_t *timer)
+ }
+ }
+
+-static void tcp_disconnect(struct session *s, int errcode)
+-{
+- if (kr_log_is_debug(IO, NULL)) {
+- struct sockaddr *peer = session_get_peer(s);
+- char *peer_str = kr_straddr(peer);
+- kr_log_debug(IO, "=> connection to '%s' closed by peer (%s)\n",
+- peer_str ? peer_str : "",
+- uv_strerror(errcode));
+- }
+-
+- if (!session_was_useful(s) && session_flags(s)->outgoing) {
+- /* We want to penalize the IP address, if a task is asking a query.
+- * It might not be the right task, but that doesn't matter so much
+- * for attributing the useless session to the IP address. */
+- struct qr_task *t = session_tasklist_get_first(s);
+- struct kr_query *qry = NULL;
+- if (t) {
+- struct kr_request *req = worker_task_request(t);
+- qry = array_tail(req->rplan.pending);
+- }
+- if (qry) /* We reuse the error for connection, as it's quite similar. */
+- qry->server_selection.error(qry, worker_task_get_transport(t),
+- KR_SELECTION_TCP_CONNECT_FAILED);
+- }
+- worker_end_tcp(s);
+-}
+-
+ static void tcp_recv(uv_stream_t *handle, ssize_t nread, const uv_buf_t *buf)
+ {
+ struct session *s = handle->data;
+@@ -381,7 +354,16 @@ static void tcp_recv(uv_stream_t *handle, ssize_t nread, const uv_buf_t *buf)
+ }
+
+ if (nread < 0 || !buf->base) {
+- tcp_disconnect(s, nread);
++ if (kr_log_is_debug(IO, NULL)) {
++ struct sockaddr *peer = session_get_peer(s);
++ char *peer_str = kr_straddr(peer);
++ kr_log_debug(IO, "=> connection to '%s' closed by peer (%s)\n",
++ peer_str ? peer_str : "",
++ uv_strerror(nread));
++ }
++
++ session_tcp_penalize(s);
++ worker_end_tcp(s);
+ return;
+ }
+
+diff --git a/daemon/session.c b/daemon/session.c
+index a1f2207..ed0ff68 100644
+--- a/daemon/session.c
++++ b/daemon/session.c
+@@ -123,11 +123,6 @@ void session_close(struct session *session)
+ }
+ }
+
+-bool session_was_useful(const struct session *session)
+-{
+- return session->was_useful;
+-}
+-
+ int session_start_read(struct session *session)
+ {
+ return io_start_read(session->handle);
+@@ -582,6 +577,24 @@ ssize_t session_wirebuf_trim(struct session *session, ssize_t len)
+ return len;
+ }
+
++void session_tcp_penalize(struct session *s)
++{
++ if (s->was_useful || !s->sflags.outgoing)
++ return;
++ /* We want to penalize the IP address, if a task is asking a query.
++ * It might not be the right task, but that doesn't matter so much
++ * for attributing the useless session to the IP address. */
++ struct qr_task *t = session_tasklist_get_first(s);
++ struct kr_query *qry = NULL;
++ if (t) {
++ struct kr_request *req = worker_task_request(t);
++ qry = array_tail(req->rplan.pending);
++ }
++ if (qry) /* We reuse the error for connection, as it's quite similar. */
++ qry->server_selection.error(qry, worker_task_get_transport(t),
++ KR_SELECTION_TCP_CONNECT_FAILED);
++}
++
+ knot_pkt_t *session_produce_packet(struct session *session, knot_mm_t *mm)
+ {
+ session->sflags.wirebuf_error = false;
+@@ -617,6 +630,7 @@ knot_pkt_t *session_produce_packet(struct session *session, knot_mm_t *mm)
+ msg_size = knot_wire_read_u16(msg_start);
+ if (msg_size >= session->wire_buf_size) {
+ session->sflags.wirebuf_error = true;
++ session_tcp_penalize(session);
+ return NULL;
+ }
+ if (msg_size + 2 > wirebuf_msg_data_size) {
+@@ -624,6 +638,7 @@ knot_pkt_t *session_produce_packet(struct session *session, knot_mm_t *mm)
+ }
+ if (msg_size == 0) {
+ session->sflags.wirebuf_error = true;
++ session_tcp_penalize(session);
+ return NULL;
+ }
+ msg_start += 2;
+@@ -631,6 +646,7 @@ knot_pkt_t *session_produce_packet(struct session *session, knot_mm_t *mm)
+ msg_size = wirebuf_msg_data_size;
+ } else {
+ session->sflags.wirebuf_error = true;
++ session_tcp_penalize(session);
+ return NULL;
+ }
+
+diff --git a/daemon/session.h b/daemon/session.h
+index 603d7cb..1f95ac5 100644
+--- a/daemon/session.h
++++ b/daemon/session.h
+@@ -91,8 +91,9 @@ int session_tasklist_finalize_expired(struct session *session);
+ /** Both of task lists (associated & waiting). */
+ /** Check if empty. */
+ bool session_is_empty(const struct session *session);
+-/** Return whether session seems to have done something useful. */
+-bool session_was_useful(const struct session *session);
++/** Penalize this server if the session hasn't been useful (and is outgoing). */
++void session_tcp_penalize(struct session *session);
++
+ /** Get pointer to session flags */
+ struct session_flags *session_flags(struct session *session);
+ /** Get pointer to peer address. */