mirror of
https://github.com/kernelkit/infix.git
synced 2026-07-22 01:13:00 +02:00
statd: avahi: suppress transient mDNS daemon restart errors
When the mdns service is stop-started (e.g. after a config change), statd's avahi client fires AVAHI_CLIENT_FAILURE momentarily. With AVAHI_CLIENT_NO_FAIL the client reconnects automatically, but the immediate ERROR log is misleading: ERROR: avahi: client failure: Daemon connection failed New behavior: - On AVAHI_CLIENT_FAILURE: start a 2 s deferred timer (no immediate log) - Timer fires up to 3 times (~6 s total); on the 3rd attempt, check if mDNS is enabled in the running config via a temporary sysrepo session - Log ERROR only if the daemon is still down AND mDNS is enabled - On AVAHI_CLIENT_S_RUNNING: cancel the timer, reset the counter, and log NOTE "mDNS daemon reconnected" if a failure had been seen This silences the error entirely when the operator has disabled mDNS (expected), and defers it by ~6 s for a brief restart (self-heals before the timer fires). Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
+80
-6
@@ -16,6 +16,8 @@
|
||||
* (same thread — no locking required).
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -683,6 +685,62 @@ static void type_browser_cb(AvahiServiceTypeBrowser *b,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if mDNS is enabled in the running datastore.
|
||||
* Opens a temporary session to avoid disturbing the operational-DS session.
|
||||
* Returns true if enabled or if the check cannot be performed (fail-safe).
|
||||
*/
|
||||
static bool mdns_is_enabled(struct avahi_ctx *ctx)
|
||||
{
|
||||
sr_session_ctx_t *sess = NULL;
|
||||
sr_data_t *data = NULL;
|
||||
const char *s;
|
||||
bool enabled = true; /* fail-safe: assume enabled */
|
||||
|
||||
if (!ctx->sr_conn)
|
||||
return true;
|
||||
|
||||
if (sr_session_start(ctx->sr_conn, SR_DS_RUNNING, &sess))
|
||||
return true;
|
||||
|
||||
if (!sr_get_node(sess, "/infix-services:mdns/enabled", 0, &data) && data) {
|
||||
s = lyd_get_value(data->tree);
|
||||
if (s && !strcmp(s, "false"))
|
||||
enabled = false;
|
||||
sr_release_data(data);
|
||||
}
|
||||
|
||||
sr_session_stop(sess);
|
||||
return enabled;
|
||||
}
|
||||
|
||||
/*
|
||||
* Retry timer callback: fires 2 s after AVAHI_CLIENT_FAILURE (and repeats up
|
||||
* to 3 times). Only logs ERROR once all retries are exhausted AND mDNS is
|
||||
* enabled in the running config — this avoids noisy errors when the operator
|
||||
* has simply disabled the mDNS service.
|
||||
*
|
||||
* Example log (mDNS enabled, daemon stays down):
|
||||
* avahi: mDNS daemon not responding (attempt 3/3) — check that the mdns
|
||||
* service is running
|
||||
*/
|
||||
static void avahi_retry_cb(struct ev_loop *loop, ev_timer *w, int revents)
|
||||
{
|
||||
struct avahi_ctx *ctx = (struct avahi_ctx *)
|
||||
((char *)w - offsetof(struct avahi_ctx, retry_timer));
|
||||
|
||||
ctx->fail_count++;
|
||||
if (ctx->fail_count < 3) {
|
||||
ev_timer_set(w, 2.0, 0.0);
|
||||
ev_timer_start(loop, w);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mdns_is_enabled(ctx))
|
||||
ERROR("avahi: mDNS daemon not responding (attempt %d/3) — "
|
||||
"check that the mdns service is running", ctx->fail_count);
|
||||
}
|
||||
|
||||
static void client_cb(AvahiClient *c, AvahiClientState state, void *userdata)
|
||||
{
|
||||
struct avahi_ctx *ctx = userdata;
|
||||
@@ -691,6 +749,11 @@ static void client_cb(AvahiClient *c, AvahiClientState state, void *userdata)
|
||||
|
||||
switch (state) {
|
||||
case AVAHI_CLIENT_S_RUNNING:
|
||||
if (ctx->fail_count > 0) {
|
||||
ev_timer_stop(ctx->loop, &ctx->retry_timer);
|
||||
NOTE("avahi: mDNS daemon reconnected");
|
||||
ctx->fail_count = 0;
|
||||
}
|
||||
INFO("avahi: client running");
|
||||
if (ctx->type_browser)
|
||||
break; /* Already browsing */
|
||||
@@ -707,13 +770,20 @@ static void client_cb(AvahiClient *c, AvahiClientState state, void *userdata)
|
||||
break;
|
||||
|
||||
case AVAHI_CLIENT_FAILURE:
|
||||
ERROR("avahi: client failure: %s",
|
||||
avahi_strerror(avahi_client_errno(c)));
|
||||
|
||||
/*
|
||||
* Browsers are internally invalidated when the daemon dies.
|
||||
* Free them explicitly here so they're recreated on reconnect.
|
||||
* The daemon went away. AVAHI_CLIENT_NO_FAIL means the client
|
||||
* will reconnect automatically — we just need to clean up the
|
||||
* now-invalid browsers so they're recreated on reconnect.
|
||||
*
|
||||
* Suppress the immediate ERROR; start a 2-second timer that
|
||||
* will log only if the daemon stays down for 3 attempts (~6 s)
|
||||
* and mDNS is enabled in the running config.
|
||||
*/
|
||||
if (!ev_is_active(&ctx->retry_timer)) {
|
||||
ev_timer_init(&ctx->retry_timer, avahi_retry_cb, 2.0, 0.0);
|
||||
ev_timer_start(ctx->loop, &ctx->retry_timer);
|
||||
}
|
||||
|
||||
{
|
||||
struct avahi_type_entry *te;
|
||||
|
||||
@@ -749,7 +819,8 @@ int avahi_ctx_init(struct avahi_ctx *ctx, struct ev_loop *loop, sr_conn_ctx_t *s
|
||||
int avahi_err;
|
||||
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
ctx->loop = loop;
|
||||
ctx->loop = loop;
|
||||
ctx->sr_conn = sr_conn;
|
||||
LIST_INIT(&ctx->neighbors);
|
||||
LIST_INIT(&ctx->services);
|
||||
LIST_INIT(&ctx->type_entries);
|
||||
@@ -790,6 +861,9 @@ void avahi_ctx_exit(struct avahi_ctx *ctx)
|
||||
{
|
||||
struct avahi_type_entry *te;
|
||||
|
||||
if (ev_is_active(&ctx->retry_timer))
|
||||
ev_timer_stop(ctx->loop, &ctx->retry_timer);
|
||||
|
||||
/* Free browsers explicitly before freeing the client */
|
||||
while (!LIST_EMPTY(&ctx->type_entries)) {
|
||||
te = LIST_FIRST(&ctx->type_entries);
|
||||
|
||||
@@ -53,10 +53,13 @@ struct avahi_type_entry {
|
||||
|
||||
struct avahi_ctx {
|
||||
struct ev_loop *loop;
|
||||
sr_conn_ctx_t *sr_conn; /* Connection for running-DS config queries */
|
||||
sr_session_ctx_t *sr_ses; /* Dedicated operational DS write session */
|
||||
AvahiClient *client;
|
||||
AvahiServiceTypeBrowser *type_browser;
|
||||
AvahiPoll poll_api; /* libev-backed vtable */
|
||||
unsigned int fail_count; /* Consecutive avahi-daemon connection failures */
|
||||
ev_timer retry_timer; /* Deferred error-log timer */
|
||||
LIST_HEAD(, avahi_neighbor) neighbors;
|
||||
LIST_HEAD(, avahi_service) services; /* Flat list; keyed by 5-tuple */
|
||||
LIST_HEAD(, avahi_type_entry) type_entries;
|
||||
|
||||
Reference in New Issue
Block a user