From bf2dc85619aa8253659fe478f7511b9b519c3529 Mon Sep 17 00:00:00 2001 From: Laurent Ghigonis Date: Fri, 28 Jun 2013 01:31:13 +0200 Subject: libglouglou: traceroute: improve hops counting --- libglouglou/libggnet_traceroute.c | 66 +++++++++++++++++++++------------------ libglouglou/libggnet_traceroute.h | 3 +- 2 files changed, 38 insertions(+), 31 deletions(-) diff --git a/libglouglou/libggnet_traceroute.c b/libglouglou/libggnet_traceroute.c index 352cb0b..c7b095b 100644 --- a/libglouglou/libggnet_traceroute.c +++ b/libglouglou/libggnet_traceroute.c @@ -83,8 +83,7 @@ static struct ggnet_traceroute_hop * _hop_ip_id(struct ggnet_traceroute_req *, int); static struct ggnet_traceroute_hop * _hop_sport(struct ggnet_traceroute_req *, int); -static struct ggnet_traceroute_hop * - _hop_last(struct ggnet_traceroute_req *); +static void _trace_done(struct ggnet_traceroute_req *); static int pcap_dloff(pcap_t *); // XXX move to libggnet_utils ? double timeval_diff(struct timeval *, struct timeval *); @@ -259,10 +258,12 @@ ggnet_traceroute_report(struct ggnet_traceroute_req *req) { #define left (sizeof(report) - (p - report)) p = report; - if (req->hopcount != 0) - p += (u_char)snprintf(p, left, "%d hops\n", req->hopcount); + if (req->target->ttl > 0) + p += (u_char)snprintf(p, left, "target:\t\tanswering\n"); else - p += (u_char)snprintf(p, left, "target not answering\n"); + p += (u_char)snprintf(p, left, "target:\t\tnot answering\n"); + p += (u_char)snprintf(p, left, "hops total:\t%d\n", req->hopcount_total); + p += (u_char)snprintf(p, left, "hops answering:\t%d\n", req->hopcount_answering); TAILQ_FOREACH(hop, &req->hops_list, entry) { p += (u_char)snprintf(p, left, "%.2d: %s %s %.2f [XXX %p]\n", hop->ttl, addr_ntoa(&hop->ip), hop->answer, hop->delay, hop); } @@ -486,19 +487,13 @@ static void _cb_trace_timeout(evutil_socket_t fd, short what, void *arg) { struct ggnet_traceroute_req *req; - struct ggnet_traceroute_hop *last; req = arg; if (req->ggtr->verbose) printf("XXX cbggnet_traceroute cb_trace_timeout (%s -> %s)\n", addr_ntoa(&req->srcip), addr_ntoa(&req->target->ip)); - last = _hop_last(req); - if (req->ggtr->verbose) - printf("XXX last %p\n", last); - if (last) - req->target->ttl = last->ttl + 1; - req->cb_done(req, req->data); + _trace_done(req); } static void @@ -538,30 +533,41 @@ _hop_sport(struct ggnet_traceroute_req *req, int sport) return NULL; } -/** - * Returns the target hop, and clean the hops_list before calling user callback - * Also sets the hopcount +/** Called at the end of a traceroute + * - Clean the hops_list by removing last non-answering hops + * - Updates target ttl + * - Count answering and total hops + * - Calls user callback */ -static struct ggnet_traceroute_hop * -_hop_last(struct ggnet_traceroute_req *req) +static void +_trace_done(struct ggnet_traceroute_req *req) { - struct ggnet_traceroute_hop *h, *ht; - struct ggnet_traceroute_hop *last = NULL; - int found = 0; - int count = 0; - - TAILQ_FOREACH_SAFE(h, &req->hops_list, entry, ht) { - count++; - if (found) + struct ggnet_traceroute_hop *h, *ht, *hp; + int hopcount_total = 0; + int hopcount_answering = 0; + + TAILQ_FOREACH_REVERSE_SAFE(h, &req->hops_list, tailhead, entry, ht) { + if (h->answer_count) { + if (addr_cmp(&h->ip, &req->target->ip) == 0) { + req->target->ttl = h->ttl + 1; + hp = TAILQ_PREV(h, tailhead, entry); + if (hp && (addr_cmp(&hp->ip, &req->target->ip) == 0)) { + TAILQ_REMOVE(&req->hops_list, h, entry); + continue; + } + } + hopcount_answering++; + } + if (hopcount_answering > 0) + hopcount_total++; + else { TAILQ_REMOVE(&req->hops_list, h, entry); - else if (addr_cmp(&h->ip, &req->target->ip) == 0) { - last = h; - found = 1; - req->hopcount = count; } } + req->hopcount_total = hopcount_total; + req->hopcount_answering = hopcount_answering; - return last; + req->cb_done(req, req->data); } static int diff --git a/libglouglou/libggnet_traceroute.h b/libglouglou/libggnet_traceroute.h index dbbb9ec..1d28299 100644 --- a/libglouglou/libggnet_traceroute.h +++ b/libglouglou/libggnet_traceroute.h @@ -55,7 +55,8 @@ struct ggnet_traceroute_req { struct ggnet_traceroute_hop *target; struct addr srcip; struct ggnet_traceroute_req_params *params; - int hopcount; + int hopcount_total; + int hopcount_answering; TAILQ_HEAD(tailhead, ggnet_traceroute_hop) hops_list; struct { struct event *ev_recv; -- cgit v1.2.3-59-g8ed1b