From 2cd60c7e775b481332703d9674f02c68ab3b3e91 Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Thu, 5 Mar 2020 09:10:32 +0200 Subject: Attempt better diagnosis of duplicate replies * src/ping903.h (hostping): New member nreply - an array counting replies for each echo request. * src/pinger.c (hostping_create): Allocate nreply array. (seqidx): Remove "replied", introduce "ping_num" instead. Ping_num is the ordinal number of the echo request that was assigned this sequence number. It is used to address the host->nreply array. (seqno_alloc): Initialize ping_num to the number of transmitted echos (i.e. next ordinal number). (hostping_from_seqno): Diagnose all possible (and impossible) variants of duplicate and unsolicited replies. --- src/ping903.h | 1 + src/pinger.c | 34 ++++++++++++++++++++++++++-------- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/src/ping903.h b/src/ping903.h index ccf62b7..3e88c17 100644 --- a/src/ping903.h +++ b/src/ping903.h @@ -142,6 +142,7 @@ typedef struct hostping { struct host_stat stat_last; struct hostping *prev, *next; + int nreply[1]; } HOSTPING; extern int verbose; diff --git a/src/pinger.c b/src/pinger.c index 2291a48..65e8e6a 100644 --- a/src/pinger.c +++ b/src/pinger.c @@ -114,10 +114,14 @@ hostping_free(HOSTPING *hp) static HOSTPING * hostping_create(char const *name, struct sockaddr *addr, socklen_t addrlen) { - HOSTPING *hp = malloc(sizeof(*hp)); + HOSTPING *hp; + size_t hostsize = sizeof(*hp) + + (ping_count - 1) * sizeof(hp->nreply[0]); + + hp = malloc(hostsize); if (hp) { - memset(hp, 0, sizeof(*hp)); + memset(hp, 0, hostsize); hp->tmin = HOSTPING_TMIN_INIT; hp->name = strdup(name); if (!hp) @@ -306,6 +310,7 @@ hostping_reset(HOSTPING *host) host->tmax = 0; host->tsum = 0; host->tsumsq = 0; + memset(host->nreply, 0, ping_count * sizeof(host->nreply[0])); switch (host->stat_last.status) { case HOST_STAT_INIT: break; @@ -942,7 +947,7 @@ enum { struct seqidx { HOSTPING *host; struct timeval tv; - int replied; + int ping_num; }; static struct seqidx *seqidx; @@ -958,7 +963,7 @@ seqno_alloc(HOSTPING *host, struct timeval *tv) if (tv->tv_sec - seqidx[n].tv.tv_sec > MAX_PING_TIMEOUT) { memcpy(&seqidx[n].tv, tv, sizeof(*tv)); seqidx[n].host = host; - seqidx[n].replied = 0; + seqidx[n].ping_num = host->xmit_count; next_seqno = (n + 1) % MOD_SEQNO; return n; } @@ -976,13 +981,26 @@ hostping_from_seqno(int seq) pthread_mutex_lock(&seqno_mutex); host = seqidx[seq].host; if (host) { + int n; + hostping_lock(host); - if (seqidx[seq].replied) { - host->dup_count++; - info("%s:%d: DUP!", host->name, seq); + n = seqidx[seq].ping_num; + if (n >= 0 && n < ping_count) { + if (++host->nreply[n] > 1) { + host->dup_count++; + info("%s: duplicate reply for echo #%d, seqno %d", + host->name, n, seq); + host = NULL; + } else if (host->recv_count == host->xmit_count) { + error("%s: unexpected reply #%d, seqno %d", + host->name, n, seq); + host = NULL; + } + } else { + error("%s: duplicate reply for unregistered echo #%d, seqno %d", + host->name, n, seq); host = NULL; } - seqidx[seq].replied++; } else fatal("no host found for sequence number %d", seq); pthread_mutex_unlock(&seqno_mutex); -- cgit v1.2.1