From b7343ed2562822dc9eee9deaa9680c56f7263916 Mon Sep 17 00:00:00 2001 From: David Schweikert Date: Tue, 23 Jul 2013 00:25:53 +0200 Subject: [PATCH] start work on seqmap --- src/Makefile.am | 4 +- src/seqmap.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++++ src/seqmap.h | 16 +++++++ 3 files changed, 137 insertions(+), 2 deletions(-) create mode 100644 src/seqmap.c create mode 100644 src/seqmap.h diff --git a/src/Makefile.am b/src/Makefile.am index 93d108e..5607a00 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -9,8 +9,8 @@ endif sbin_PROGRAMS = ${prog} -fping_SOURCES = fping.c options.h +fping_SOURCES = fping.c options.h seqmap.h seqmap.c fping_DEPENDENCIES = ../config.h -fping6_SOURCES = fping.c options.h +fping6_SOURCES = fping.c options.h seqmap.h seqmap.c fping6_DEPENDENCIES = ../config.h fping6_CFLAGS = $(AM_CFLAGS) -DIPV6 diff --git a/src/seqmap.c b/src/seqmap.c new file mode 100644 index 0000000..2e6c030 --- /dev/null +++ b/src/seqmap.c @@ -0,0 +1,119 @@ +/* + * fping: fast-ping, file-ping, favorite-ping, funky-ping + * + * Ping a list of target hosts in a round robin fashion. + * A better ping overall. + * + * fping website: http://www.fping.org + * + * Current maintainer of fping: David Schweikert + * Please send suggestions and patches to: david@schweikert.ch + * + * + * Original author: Roland Schemers + * IPv6 Support: Jeroen Massar + * Improved main loop: David Schweikert + * Debian Merge, TOS settings: Tobi Oetiker + * Bugfixes, byte order & senseful seq.-numbers: Stephan Fuhrmann (stephan.fuhrmann AT 1und1.de) + * + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Stanford University. The name of the University may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * seqmap.c: implementation of a mapping between sequence number and (host, ping_nr) + * we can't just use ping_nr*host_count + host_nr, because it can + * overflow the 16 bit of the icmp header field. See also: + * https://github.com/schweikert/fping/issues/48 + */ + +#include "seqmap.h" +#include "options.h" +#include "limits.h" + +#include +#include + +/* description of the data structure used: + * + * - we assume that no more than SEQMAP_MAXSEQ (65000) pings are sent in + * the timeout interval (SEQMAP_TIMEOUT_IN_S) + * - we store the values in an array with SEQMAP_MAXSEQ elements + * - current sequence number % SEQMAP_MAXSEQ gives the current index + * - when entering a value, we check that the current entry is expired + */ + +static SEQMAP_VALUE *seqmap_map = NULL; +static unsigned int seqmap_next_id = 0; +static SEQMAP_VALUE *seqmap_free_list; + +#define SEQMAP_TIMEOUT_IN_S 10 +#define SEQMAP_UNASSIGNED_HOST_NR UINT_MAX + +void seqmap_init() +{ + unsigned int i; + + seqmap_map = calloc(SEQMAP_MAXSEQ, sizeof(SEQMAP_VALUE)); + if(seqmap_map == NULL) { + perror("malloc error (can't allocate seqmap_map)"); + } +} + +unsigned int seqmap_add(unsigned int host_nr, unsigned int ping_count, struct timeval *now) +{ + unsigned int current_id; + SEQMAP_VALUE *next_value; + + if(!seqmap_map) { + fprintf(stderr, "fping internal error: seqmap not initialized.\n"); + exit(4); + } + + /* check if expired (note that unused seqmap values will have fields set to + * 0, so will be seen as expired */ + next_value = &seqmap_map[seqmap_next_id]; + if(next_value->ping_ts.tv_sec != 0 && (now->tv_sec - next_value->ping_ts.tv_sec) < SEQMAP_TIMEOUT_IN_S) { + fprintf(stderr, "fping error: not enough sequence numbers available! (expire_timeout=%d, host_nr=%d, ping_count=%d, seqmap_next_id=%d)\n", + SEQMAP_TIMEOUT_IN_S, host_nr, ping_count, seqmap_next_id); + exit(4); + } + + /* store the value */ + next_value->host_nr = host_nr; + next_value->ping_count = ping_count; + next_value->ping_ts.tv_sec = now->tv_sec; + next_value->ping_ts.tv_usec = now->tv_usec; + + /* increase next id */ + current_id = seqmap_next_id; + seqmap_next_id = (seqmap_next_id + 1) % SEQMAP_MAXSEQ; + + return current_id; +} + +SEQMAP_VALUE *seqmap_fetch(unsigned int id, struct timeval *now) +{ + SEQMAP_VALUE *value; + + if(id > SEQMAP_MAXSEQ) { + return NULL; + } + + value = &seqmap_map[id]; + + /* verify that value is not expired */ + if(now->tv_sec - value->ping_ts.tv_sec >= SEQMAP_TIMEOUT_IN_S) { + return NULL; + } + + return value; +} diff --git a/src/seqmap.h b/src/seqmap.h new file mode 100644 index 0000000..0887e68 --- /dev/null +++ b/src/seqmap.h @@ -0,0 +1,16 @@ +#ifndef SEQMAP_H +#define SEQMAP_H + +#include + +typedef struct seqmap_value +{ + unsigned int host_nr; + unsigned int ping_count; + struct timeval ping_ts; + +} SEQMAP_VALUE; + +#define SEQMAP_MAXSEQ 65000 + +#endif