netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* RE: "-w deadline" bug in ping/iputils- i will provide fix if you can tell me where owner of iputils is. Thanks.
       [not found] <7D3B6706FA74174B8C1AC24710890745136F1A0BF1@USNAVSXCHMBSA1.ndc.alcatel-lucent.com>
@ 2012-01-04 20:56 ` Cloutier, Joseph (Joseph)
  2012-01-09 15:45   ` YOSHIFUJI Hideaki
  0 siblings, 1 reply; 5+ messages in thread
From: Cloutier, Joseph (Joseph) @ 2012-01-04 20:56 UTC (permalink / raw)
  To: 'Linus Torvalds', 'netdev@vger.kernel.org'
  Cc: 'torvalds@osdl.org'



-----Original Message-----
From: Cloutier, Joseph (Joseph)
Sent: Wednesday, January 04, 2012 3:55 PM
To: 'Linus Torvalds'; 'netdev@vger.kernel.org'
Cc: 'torvalds@osdl.org'
Subject: RE: "-w deadline" bug in ping/iputils- i will provide fix if
you can tell me where owner of iputils is. Thanks.


netdev@vger.kernel.org.

I have made a fix for the "-w deadline" issue to iputils-s20101006.tar.bz2.  There are 4 places in the code with the fix, identified by my name, Joe Cloutier- ALU.

There are 2 bugs fixed:
*       For flood pings if the "-w" option is set then more pings than "-c x" are sent out.
*       The "-w x" timer should be set after he last "-c x" ping is sent out.

Linux flood ping is an invaluable tool for us to use when trouble shooting wireless network problems.  It is a very fast way to verify things like PVC allocations, duplex miss-matches, fiber problems, egress queue settins, etc.

I have modified 2 ping versions (one an older one prior to the shared library change many years ago, and then Redhat 8.0 release), but my Management does not my copies released to our Customers because the code is "unsupported".

If you would accept these changes then I can direct our Customers to use the official Linux flood ping option.

I have tested the code using Linux release 14 and the latest gcc compiler.  It is doing what it should now.

Thanks, Joe Cloutier

Created with tar cjvf ...

-----Original Message-----
From: linus971@gmail.com [mailto:linus971@gmail.com]On Behalf Of Linus
Torvalds
Sent: Thursday, December 08, 2011 8:49 PM
To: Cloutier, Joseph (Joseph)
Cc: torvalds@osdl.org
Subject: Re: "-w deadline" bug in ping/iputils- i will provide fix if
you can tell me where owner of iputils is. Thanks.


On Thu, Dec 8, 2011 at 1:54 PM, Cloutier, Joseph (Joseph)
<joseph.cloutier@alcatel-lucent.com> wrote:
>

See

  http://www.skbuff.net/iputils/

afaik,

               Linus

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: "-w deadline" bug in ping/iputils- i will provide fix if you can tell me where owner of iputils is. Thanks.
  2012-01-04 20:56 ` "-w deadline" bug in ping/iputils- i will provide fix if you can tell me where owner of iputils is. Thanks Cloutier, Joseph (Joseph)
@ 2012-01-09 15:45   ` YOSHIFUJI Hideaki
  2012-01-09 17:26     ` Cloutier, Joseph (Joseph)
  0 siblings, 1 reply; 5+ messages in thread
From: YOSHIFUJI Hideaki @ 2012-01-09 15:45 UTC (permalink / raw)
  To: Cloutier, Joseph (Joseph)
  Cc: 'Linus Torvalds', 'netdev@vger.kernel.org',
	'torvalds@osdl.org', YOSHIFUJI Hideaki

Cloutier, Joseph (Joseph) wrote:
>
>
> -----Original Message-----
> From: Cloutier, Joseph (Joseph)
> Sent: Wednesday, January 04, 2012 3:55 PM
> To: 'Linus Torvalds'; 'netdev@vger.kernel.org'
> Cc: 'torvalds@osdl.org'
> Subject: RE: "-w deadline" bug in ping/iputils- i will provide fix if
> you can tell me where owner of iputils is. Thanks.
>
>
> netdev@vger.kernel.org.
>
> I have made a fix for the "-w deadline" issue to iputils-s20101006.tar.bz2.  There are 4 places in the code with the fix, identified by my name, Joe Cloutier- ALU.
>
> There are 2 bugs fixed:
> *       For flood pings if the "-w" option is set then more pings than "-c x" are sent out.
> *       The "-w x" timer should be set after he last "-c x" ping is sent out.
>
> Linux flood ping is an invaluable tool for us to use when trouble shooting wireless network problems.  It is a very fast way to verify things like PVC allocations, duplex miss-matches, fiber problems, egress queue settins, etc.
>
> I have modified 2 ping versions (one an older one prior to the shared library change many years ago, and then Redhat 8.0 release), but my Management does not my copies released to our Customers because the code is "unsupported".
>
> If you would accept these changes then I can direct our Customers to use the official Linux flood ping option.
>
> I have tested the code using Linux release 14 and the latest gcc compiler.  It is doing what it should now.
>
> Thanks, Joe Cloutier
>
> Created with tar cjvf ...

I could not find any patches/tarballs unfortunately.
Would you resend it please?  Thank you.

--yoshfuji

^ permalink raw reply	[flat|nested] 5+ messages in thread

* RE: "-w deadline" bug in ping/iputils- i will provide fix if you can tell me where owner of iputils is. Thanks.
  2012-01-09 15:45   ` YOSHIFUJI Hideaki
@ 2012-01-09 17:26     ` Cloutier, Joseph (Joseph)
  2012-01-10  3:54       ` YOSHIFUJI Hideaki
  0 siblings, 1 reply; 5+ messages in thread
From: Cloutier, Joseph (Joseph) @ 2012-01-09 17:26 UTC (permalink / raw)
  To: 'YOSHIFUJI Hideaki'
  Cc: 'Linus Torvalds', 'netdev@vger.kernel.org',
	'torvalds@osdl.org'

[-- Attachment #1: Type: text/plain, Size: 2482 bytes --]

yoshfuji-  the only changes were to ping_common.c.  Here is the file.  Sorry, I rarely use tar and probably used the wrong command line parameters.

Also, I tried to test IPv6, but ran into build problems using the openssl libraries.  I finally just gave up. If you can send me some pointers on how go combine openssl builds with iputil builds I can test IPv6 for your also.

Thanks, Joe

PS- changes are bracketed by comments "deadline fix" and "end deadline fix".

-----Original Message-----
From: YOSHIFUJI Hideaki [mailto:yoshfuji@linux-ipv6.org]
Sent: Monday, January 09, 2012 10:45 AM
To: Cloutier, Joseph (Joseph)
Cc: 'Linus Torvalds'; 'netdev@vger.kernel.org'; 'torvalds@osdl.org';
YOSHIFUJI Hideaki
Subject: Re: "-w deadline" bug in ping/iputils- i will provide fix if
you can tell me where owner of iputils is. Thanks.


Cloutier, Joseph (Joseph) wrote:
>
>
> -----Original Message-----
> From: Cloutier, Joseph (Joseph)
> Sent: Wednesday, January 04, 2012 3:55 PM
> To: 'Linus Torvalds'; 'netdev@vger.kernel.org'
> Cc: 'torvalds@osdl.org'
> Subject: RE: "-w deadline" bug in ping/iputils- i will provide fix if
> you can tell me where owner of iputils is. Thanks.
>
>
> netdev@vger.kernel.org.
>
> I have made a fix for the "-w deadline" issue to iputils-s20101006.tar.bz2.  There are 4 places in the code with the fix, identified by my name, Joe Cloutier- ALU.
>
> There are 2 bugs fixed:
> *       For flood pings if the "-w" option is set then more pings than "-c x" are sent out.
> *       The "-w x" timer should be set after he last "-c x" ping is sent out.
>
> Linux flood ping is an invaluable tool for us to use when trouble shooting wireless network problems.  It is a very fast way to verify things like PVC allocations, duplex miss-matches, fiber problems, egress queue settins, etc.
>
> I have modified 2 ping versions (one an older one prior to the shared library change many years ago, and then Redhat 8.0 release), but my Management does not my copies released to our Customers because the code is "unsupported".
>
> If you would accept these changes then I can direct our Customers to use the official Linux flood ping option.
>
> I have tested the code using Linux release 14 and the latest gcc compiler.  It is doing what it should now.
>
> Thanks, Joe Cloutier
>
> Created with tar cjvf ...

I could not find any patches/tarballs unfortunately.
Would you resend it please?  Thank you.

--yoshfuji

[-- Attachment #2: ping_common.c --]
[-- Type: text/plain, Size: 22509 bytes --]

#include "ping_common.h"
#include <ctype.h>
#include <sched.h>

int options;

int mark;
int sndbuf;
int ttl;
int rtt;
int rtt_addend;
__u16 acked;

int mx_dup_ck = MAX_DUP_CHK;
char rcvd_tbl[MAX_DUP_CHK / 8];


/* counters */
long npackets;			/* max packets to transmit */
long nreceived;			/* # of packets we got back */
long nrepeats;			/* number of duplicates */
long ntransmitted;		/* sequence # for outbound packets = #sent */
long nchecksum;			/* replies with bad checksum */
long nerrors;			/* icmp errors */
int interval = 1000;		/* interval between packets (msec) */
int preload;
int deadline = 0;		/* time to die */
int lingertime = MAXWAIT*1000;
struct timeval start_time, cur_time;
volatile int exiting;
volatile int status_snapshot;
int confirm = 0;

/* Stupid workarounds for bugs/missing functionality in older linuces.
 * confirm_flag fixes refusing service of kernels without MSG_CONFIRM.
 * i.e. for linux-2.2 */
int confirm_flag = MSG_CONFIRM;
/* And this is workaround for bug in IP_RECVERR on raw sockets which is present
 * in linux-2.2.[0-19], linux-2.4.[0-7] */
int working_recverr;

/* timing */
int timing;			/* flag to do timing */
long tmin = LONG_MAX;		/* minimum round trip time */
long tmax;			/* maximum round trip time */
/* Message for rpm maintainers: have _shame_. If you want
 * to fix something send the patch to me for sanity checking.
 * "sparcfix" patch is a complete non-sense, apparenly the person
 * prepared it was stoned.
 */
long long tsum;			/* sum of all times, for doing average */
long long tsum2;
int  pipesize = -1;

int datalen = DEFDATALEN;

char *hostname;
int uid;
int ident;			/* process id to identify our packets */

static int screen_width = INT_MAX;

/* Fills all the outpack, excluding ICMP header, but _including_
 * timestamp area with supplied pattern.
 */
static void fill(char *patp)
{
	int ii, jj, kk;
	int pat[16];
	char *cp;
	u_char *bp = outpack+8;

	for (cp = patp; *cp; cp++) {
		if (!isxdigit(*cp)) {
			fprintf(stderr,
				"ping: patterns must be specified as hex digits.\n");
			exit(2);
		}
	}
	ii = sscanf(patp,
	    "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
	    &pat[0], &pat[1], &pat[2], &pat[3], &pat[4], &pat[5], &pat[6],
	    &pat[7], &pat[8], &pat[9], &pat[10], &pat[11], &pat[12],
	    &pat[13], &pat[14], &pat[15]);

	if (ii > 0) {
		for (kk = 0; kk <= maxpacket - (8 + ii); kk += ii)
			for (jj = 0; jj < ii; ++jj)
				bp[jj + kk] = pat[jj];
	}
	if (!(options & F_QUIET)) {
		printf("PATTERN: 0x");
		for (jj = 0; jj < ii; ++jj)
			printf("%02x", bp[jj] & 0xFF);
		printf("\n");
	}
}

void common_options(int ch)
{
	switch(ch) {
	case 'a':
		options |= F_AUDIBLE;
		break;
	case 'A':
		options |= F_ADAPTIVE;
		break;
	case 'c':
		npackets = atoi(optarg);
		if (npackets <= 0) {
			fprintf(stderr, "ping: bad number of packets to transmit.\n");
			exit(2);
		}
		break;
	case 'd':
		options |= F_SO_DEBUG;
		break;
	case 'D':
		options |= F_PTIMEOFDAY;
		break;
	case 'i':		/* wait between sending packets */
	{
		if (strchr(optarg, '.')) {
			float t;
			if (sscanf(optarg, "%f", &t) != 1) {
				fprintf(stderr, "ping: bad timing interval.\n");
				exit(2);
			}
			interval = (int)(t*1000);
		} else if (sscanf(optarg, "%d", &interval) == 1) {
			interval *= 1000;
		} else {
			fprintf(stderr, "ping: bad timing interval.\n");
			exit(2);
		}

		if (interval < 0) {
			fprintf(stderr, "ping: bad timing interval.\n");
			exit(2);
		}
		options |= F_INTERVAL;
		break;
	}
	case 'm':
	{
		char *endp;
		mark = (int)strtoul(optarg, &endp, 10);
		if (mark < 0 || *endp != '\0') {
			fprintf(stderr, "mark cannot be negative");
			exit(2);
		}
		options |= F_MARK;
		break;
	}
	case 'w':
		deadline = atoi(optarg);
		if (deadline < 0) {
			fprintf(stderr, "ping: bad wait time.\n");
			exit(2);
		}
		break;
	case 'l':
		preload = atoi(optarg);
		if (preload <= 0) {
			fprintf(stderr, "ping: bad preload value, should be 1..%d\n", mx_dup_ck);
			exit(2);
		}
		if (preload > mx_dup_ck)
			preload = mx_dup_ck;
		if (uid && preload > 3) {
			fprintf(stderr, "ping: cannot set preload to value > 3\n");
			exit(2);
		}
		break;
	case 'S':
		sndbuf = atoi(optarg);
		if (sndbuf <= 0) {
			fprintf(stderr, "ping: bad sndbuf value.\n");
			exit(2);
		}
		break;
	case 'f':
		options |= F_FLOOD;
		setbuf(stdout, (char *)NULL);
		/* fallthrough to numeric - avoid gethostbyaddr during flood */
	case 'n':
		options |= F_NUMERIC;
		break;
	case 'p':		/* fill buffer with user pattern */
		options |= F_PINGFILLED;
		fill(optarg);
		break;
	case 'q':
		options |= F_QUIET;
		break;
	case 'r':
		options |= F_SO_DONTROUTE;
		break;
	case 's':		/* size of packet to send */
		datalen = atoi(optarg);
		if (datalen < 0) {
			fprintf(stderr, "ping: illegal negative packet size %d.\n", datalen);
			exit(2);
		}
		if (datalen > maxpacket - 8) {
			fprintf(stderr, "ping: packet size too large: %d\n",
				datalen);
			exit(2);
		}
		break;
	case 'v':
		options |= F_VERBOSE;
		break;
	case 'L':
		options |= F_NOLOOP;
		break;
	case 't':
		options |= F_TTL;
		ttl = atoi(optarg);
		if (ttl < 0 || ttl > 255) {
			fprintf(stderr, "ping: ttl %u out of range\n", ttl);
			exit(2);
		}
		break;
	case 'U':
		options |= F_LATENCY;
		break;
	case 'B':
		options |= F_STRICTSOURCE;
		break;
	case 'W':
		lingertime = atoi(optarg);
		if (lingertime < 0 || lingertime > INT_MAX/1000000) {
			fprintf(stderr, "ping: bad linger time.\n");
			exit(2);
		}
		lingertime *= 1000;
		break;
	case 'V':
		printf("ping utility, iputils-ss%s\n", SNAPSHOT);
		exit(0);
	default:
		abort();
	}
}


static void sigexit(int signo)
{
	exiting = 1;
}

static void sigstatus(int signo)
{
	status_snapshot = 1;
}


int __schedule_exit(int next)
{
	static unsigned long waittime;
	struct itimerval it;

	if (waittime)
		return next;

	if (nreceived) {
		waittime = 2 * tmax;
		if (waittime < 1000*interval)
			waittime = 1000*interval;
	} else
		waittime = lingertime*1000;

	if (next < 0 || next < waittime/1000)
		next = waittime/1000;

	it.it_interval.tv_sec = 0;
	it.it_interval.tv_usec = 0;
	it.it_value.tv_sec = waittime/1000000;
	it.it_value.tv_usec = waittime%1000000;
	setitimer(ITIMER_REAL, &it, NULL);
	return next;
}

static inline void update_interval(void)
{
	int est = rtt ? rtt/8 : interval*1000;

	interval = (est+rtt_addend+500)/1000;
	if (uid && interval < MINUSERINTERVAL)
		interval = MINUSERINTERVAL;
}

/*
 * Print timestamp
 */
void print_timestamp(void)
{
	if (options & F_PTIMEOFDAY) {
		struct timeval tv;
		gettimeofday(&tv, NULL);
		printf("[%lu.%06lu] ",
		       (unsigned long)tv.tv_sec, (unsigned long)tv.tv_usec);
	}
}

/*
 * pinger --
 * 	Compose and transmit an ICMP ECHO REQUEST packet.  The IP packet
 * will be added on by the kernel.  The ID field is our UNIX process ID,
 * and the sequence number is an ascending integer.  The first 8 bytes
 * of the data portion are used to hold a UNIX "timeval" struct in VAX
 * byte-order, to compute the round-trip time.
 */
int pinger(void)
{
	static int oom_count;
	static int tokens;
	int i;

	/* Have we already sent enough? If we have, return an arbitrary positive value. */
	if (exiting || (npackets && ntransmitted >= npackets && !deadline))
		return 1000;

	/* Check that packets < rate*time + preload */
	if (cur_time.tv_sec == 0) {
		gettimeofday(&cur_time, NULL);
		tokens = interval*(preload-1);
	} else {
		long ntokens;
		struct timeval tv;

		gettimeofday(&tv, NULL);
		ntokens = (tv.tv_sec - cur_time.tv_sec)*1000 +
			(tv.tv_usec-cur_time.tv_usec)/1000;
		if (!interval) {
			/* Case of unlimited flood is special;
			 * if we see no reply, they are limited to 100pps */
			if (ntokens < MININTERVAL && in_flight() >= preload)
				return MININTERVAL-ntokens;
		}
		ntokens += tokens;
		if (ntokens > interval*preload)
			ntokens = interval*preload;
		if (ntokens < interval)
			return interval - ntokens;

		cur_time = tv;
		tokens = ntokens - interval;
	}

resend:
	i = send_probe();

	if (i == 0) {
		oom_count = 0;
		advance_ntransmitted();
		if (!(options & F_QUIET) && (options & F_FLOOD)) {
			/* Very silly, but without this output with
			 * high preload or pipe size is very confusing. */
			if ((preload < screen_width && pipesize < screen_width) ||
			    in_flight() < screen_width)
				write(STDOUT_FILENO, ".", 1);
		}
		return interval - tokens;
	}

	/* And handle various errors... */
	if (i > 0) {
		/* Apparently, it is some fatal bug. */
		abort();
	} else if (errno == ENOBUFS || errno == ENOMEM) {
		int nores_interval;

		/* Device queue overflow or OOM. Packet is not sent. */
		tokens = 0;
		/* Slowdown. This works only in adaptive mode (option -A) */
		rtt_addend += (rtt < 8*50000 ? rtt/8 : 50000);
		if (options&F_ADAPTIVE)
			update_interval();
		nores_interval = SCHINT(interval/2);
		if (nores_interval > 500)
			nores_interval = 500;
		oom_count++;
		if (oom_count*nores_interval < lingertime)
			return nores_interval;
		i = 0;
		/* Fall to hard error. It is to avoid complete deadlock
		 * on stuck output device even when dealine was not requested.
		 * Expected timings are screwed up in any case, but we will
		 * exit some day. :-) */
	} else if (errno == EAGAIN) {
		/* Socket buffer is full. */
		tokens += interval;
		return MININTERVAL;
	} else {
		if ((i=receive_error_msg()) > 0) {
			/* An ICMP error arrived. */
			tokens += interval;
			return MININTERVAL;
		}
		/* Compatibility with old linuces. */
		if (i == 0 && confirm_flag && errno == EINVAL) {
			confirm_flag = 0;
			errno = 0;
		}
		if (!errno)
			goto resend;
	}

	/* Hard local error. Pretend we sent packet. */
	advance_ntransmitted();

	if (i == 0 && !(options & F_QUIET)) {
		if (options & F_FLOOD)
			write(STDOUT_FILENO, "E", 1);
		else
			perror("ping: sendmsg");
	}
	tokens = 0;
	return SCHINT(interval);
}

/* Set socket buffers, "alloc" is an estimate of memory taken by single packet. */

void sock_setbufs(int icmp_sock, int alloc)
{
	int rcvbuf, hold;
	socklen_t tmplen = sizeof(hold);

	if (!sndbuf)
		sndbuf = alloc;
	setsockopt(icmp_sock, SOL_SOCKET, SO_SNDBUF, (char *)&sndbuf, sizeof(sndbuf));

	rcvbuf = hold = alloc * preload;
	if (hold < 65536)
		hold = 65536;
	setsockopt(icmp_sock, SOL_SOCKET, SO_RCVBUF, (char *)&hold, sizeof(hold));
	if (getsockopt(icmp_sock, SOL_SOCKET, SO_RCVBUF, (char *)&hold, &tmplen) == 0) {
		if (hold < rcvbuf)
			fprintf(stderr, "WARNING: probably, rcvbuf is not enough to hold preload.\n");
	}
}

/* Protocol independent setup and parameter checks. */

void setup(int icmp_sock)
{
	int hold;
	struct timeval tv;

	if ((options & F_FLOOD) && !(options & F_INTERVAL))
		interval = 0;

	if (uid && interval < MINUSERINTERVAL) {
		fprintf(stderr, "ping: cannot flood; minimal interval, allowed for user, is %dms\n", MINUSERINTERVAL);
		exit(2);
	}

	if (interval >= INT_MAX/preload) {
		fprintf(stderr, "ping: illegal preload and/or interval\n");
		exit(2);
	}

	hold = 1;
	if (options & F_SO_DEBUG)
		setsockopt(icmp_sock, SOL_SOCKET, SO_DEBUG, (char *)&hold, sizeof(hold));
	if (options & F_SO_DONTROUTE)
		setsockopt(icmp_sock, SOL_SOCKET, SO_DONTROUTE, (char *)&hold, sizeof(hold));

#ifdef SO_TIMESTAMP
	if (!(options&F_LATENCY)) {
		int on = 1;
		if (setsockopt(icmp_sock, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on)))
			fprintf(stderr, "Warning: no SO_TIMESTAMP support, falling back to SIOCGSTAMP\n");
	}
#endif
	if (options & F_MARK) {
		if (setsockopt(icmp_sock, SOL_SOCKET, SO_MARK,
				&mark, sizeof(mark)) == -1) {
			/* we probably dont wanna exit since old kernels
			 * dont support mark ..
			*/
			fprintf(stderr, "Warning: Failed to set mark %d\n", mark);
		}
	}

	/* Set some SNDTIMEO to prevent blocking forever
	 * on sends, when device is too slow or stalls. Just put limit
	 * of one second, or "interval", if it is less.
	 */
	tv.tv_sec = 1;
	tv.tv_usec = 0;
	if (interval < 1000) {
		tv.tv_sec = 0;
		tv.tv_usec = 1000 * SCHINT(interval);
	}
	setsockopt(icmp_sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&tv, sizeof(tv));

	/* Set RCVTIMEO to "interval". Note, it is just an optimization
	 * allowing to avoid redundant poll(). */
	tv.tv_sec = SCHINT(interval)/1000;
	tv.tv_usec = 1000*(SCHINT(interval)%1000);
	if (setsockopt(icmp_sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(tv)))
		options |= F_FLOOD_POLL;

	if (!(options & F_PINGFILLED)) {
		int i;
		u_char *p = outpack+8;

		/* Do not forget about case of small datalen,
		 * fill timestamp area too!
		 */
		for (i = 0; i < datalen; ++i)
			*p++ = i;
	}

	ident = htons(getpid() & 0xFFFF);

	set_signal(SIGINT, sigexit);
	set_signal(SIGALRM, sigexit);
	set_signal(SIGQUIT, sigstatus);

	gettimeofday(&start_time, NULL);

/* deadline fix-- Joe Cloutier ALU
   2 problems fixed:
	a) flood ping kept running pings > npackets when deadline set
	b) deadline timer should be after last npackets == ntransmitted,
	   not at beginning of flood ping run.
	if (deadline) {
		struct itimerval it;

		it.it_interval.tv_sec = 0;
		it.it_interval.tv_usec = 0;
		it.it_value.tv_sec = deadline;
		it.it_value.tv_usec = 0;
		setitimer(ITIMER_REAL, &it, NULL);
	}
   end deadline fix-- Joe Cloutier ALU */

	if (isatty(STDOUT_FILENO)) {
		struct winsize w;

		if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != -1) {
			if (w.ws_col > 0)
				screen_width = w.ws_col;
		}
	}
}

void main_loop(int icmp_sock, __u8 *packet, int packlen)
{
	char addrbuf[128];
	char ans_data[4096];
	struct iovec iov;
	struct msghdr msg;
	struct cmsghdr *c;
	int cc;
	int next;
	int polling;
	int sig_deadline = 0; /* deadline fix -- Joe Cloutier ALU */

	iov.iov_base = (char *)packet;

	for (;;) {
		/* Check exit conditions. */
		if (exiting)
			break;
		if (npackets && nreceived + nerrors >= npackets)
			break;
		if (deadline && nerrors)
			break;
		/* Check for and do special actions. */
		if (status_snapshot)
			status();
/* deadline fix -- Joe Cloutier ALU */
		if((npackets == ntransmitted) && deadline &&
			(sig_deadline == 0)){
			sig_deadline++;
			struct itimerval it;
	
			it.it_interval.tv_sec = 0;
			it.it_interval.tv_usec = 0;
			it.it_value.tv_sec = deadline;
			it.it_value.tv_usec = 0;
			setitimer(ITIMER_REAL, &it, NULL);
		}
/* end deadline fix -- Joe Cloutier ALU */

		/* Send probes scheduled to this time. */
		do {
/* deadline fix -- Joe Cloutier ALU */
			if(npackets == ntransmitted)
				break;
/* end deadline fix -- Joe Cloutier ALU */
			next = pinger();
			next = schedule_exit(next);
		} while (next <= 0);

		/* "next" is time to send next probe, if positive.
		 * If next<=0 send now or as soon as possible. */

		/* Technical part. Looks wicked. Could be dropped,
		 * if everyone used the newest kernel. :-)
		 * Its purpose is:
		 * 1. Provide intervals less than resolution of scheduler.
		 *    Solution: spinning.
		 * 2. Avoid use of poll(), when recvmsg() can provide
		 *    timed waiting (SO_RCVTIMEO). */
		polling = 0;
		if ((options & (F_ADAPTIVE|F_FLOOD_POLL)) || next<SCHINT(interval)) {
			int recv_expected = in_flight();

			/* If we are here, recvmsg() is unable to wait for
			 * required timeout. */
			if (1000*next <= 1000000/(int)HZ) {
				/* Very short timeout... So, if we wait for
				 * something, we sleep for MININTERVAL.
				 * Otherwise, spin! */
				if (recv_expected) {
					next = MININTERVAL;
				} else {
					next = 0;
					/* When spinning, no reasons to poll.
					 * Use nonblocking recvmsg() instead. */
					polling = MSG_DONTWAIT;
					/* But yield yet. */
					sched_yield();
				}
			}

			if (!polling &&
			    ((options & (F_ADAPTIVE|F_FLOOD_POLL)) || interval)) {
				struct pollfd pset;
				pset.fd = icmp_sock;
				pset.events = POLLIN|POLLERR;
				pset.revents = 0;
				if (poll(&pset, 1, next) < 1 ||
				    !(pset.revents&(POLLIN|POLLERR)))
					continue;
				polling = MSG_DONTWAIT;
			}
		}

		for (;;) {
			struct timeval *recv_timep = NULL;
			struct timeval recv_time;
			int not_ours = 0; /* Raw socket can receive messages
					   * destined to other running pings. */

			iov.iov_len = packlen;
			memset(&msg, 0, sizeof(msg));
			msg.msg_name = addrbuf;
			msg.msg_namelen = sizeof(addrbuf);
			msg.msg_iov = &iov;
			msg.msg_iovlen = 1;
			msg.msg_control = ans_data;
			msg.msg_controllen = sizeof(ans_data);

			cc = recvmsg(icmp_sock, &msg, polling);
			polling = MSG_DONTWAIT;

			if (cc < 0) {
				if (errno == EAGAIN || errno == EINTR)
					break;
				if (!receive_error_msg()) {
					if (errno) {
						perror("ping: recvmsg");
						break;
					}
					not_ours = 1;
				}
			} else {

#ifdef SO_TIMESTAMP
				for (c = CMSG_FIRSTHDR(&msg); c; c = CMSG_NXTHDR(&msg, c)) {
					if (c->cmsg_level != SOL_SOCKET ||
					    c->cmsg_type != SO_TIMESTAMP)
						continue;
					if (c->cmsg_len < CMSG_LEN(sizeof(struct timeval)))
						continue;
					recv_timep = (struct timeval*)CMSG_DATA(c);
				}
#endif

				if ((options&F_LATENCY) || recv_timep == NULL) {
					if ((options&F_LATENCY) ||
					    ioctl(icmp_sock, SIOCGSTAMP, &recv_time))
						gettimeofday(&recv_time, NULL);
					recv_timep = &recv_time;
				}

				not_ours = parse_reply(&msg, cc, addrbuf, recv_timep);
			}

			/* See? ... someone runs another ping on this host. */
			if (not_ours)
				install_filter();

			/* If nothing is in flight, "break" returns us to pinger. */
			if (in_flight() == 0)
				break;

			/* Otherwise, try to recvmsg() again. recvmsg()
			 * is nonblocking after the first iteration, so that
			 * if nothing is queued, it will receive EAGAIN
			 * and return to pinger. */
		}
	}
	finish();
}

int gather_statistics(__u8 *icmph, int icmplen,
		      int cc, __u16 seq, int hops,
		      int csfailed, struct timeval *tv, char *from,
		      void (*pr_reply)(__u8 *icmph, int cc))
{
	int dupflag = 0;
	long triptime = 0;
	__u8 *ptr = icmph + icmplen;

	++nreceived;
	if (!csfailed)
		acknowledge(seq);

	if (timing && cc >= 8+sizeof(struct timeval)) {
		struct timeval tmp_tv;
		memcpy(&tmp_tv, ptr, sizeof(tmp_tv));

restamp:
		tvsub(tv, &tmp_tv);
		triptime = tv->tv_sec * 1000000 + tv->tv_usec;
		if (triptime < 0) {
			fprintf(stderr, "Warning: time of day goes back (%ldus), taking countermeasures.\n", triptime);
			triptime = 0;
			if (!(options & F_LATENCY)) {
				gettimeofday(tv, NULL);
				options |= F_LATENCY;
				goto restamp;
			}
		}
		if (!csfailed) {
			tsum += triptime;
			tsum2 += (long long)triptime * (long long)triptime;
			if (triptime < tmin)
				tmin = triptime;
			if (triptime > tmax)
				tmax = triptime;
			if (!rtt)
				rtt = triptime*8;
			else
				rtt += triptime-rtt/8;
			if (options&F_ADAPTIVE)
				update_interval();
		}
	}

	if (csfailed) {
		++nchecksum;
		--nreceived;
	} else if (TST(seq % mx_dup_ck)) {
		++nrepeats;
		--nreceived;
		dupflag = 1;
	} else {
		SET(seq % mx_dup_ck);
		dupflag = 0;
	}
	confirm = confirm_flag;

	if (options & F_QUIET)
		return 1;

	if (options & F_FLOOD) {
		if (!csfailed)
			write(STDOUT_FILENO, "\b \b", 3);
		else
			write(STDOUT_FILENO, "\bC", 1);
	} else {
		int i;
		__u8 *cp, *dp;

		print_timestamp();
		printf("%d bytes from %s:", cc, from);

		if (pr_reply)
			pr_reply(icmph, cc);

		if (hops >= 0)
			printf(" ttl=%d", hops);

		if (cc < datalen+8) {
			printf(" (truncated)\n");
			return 1;
		}
		if (timing) {
			if (triptime >= 100000)
				printf(" time=%ld ms", triptime/1000);
			else if (triptime >= 10000)
				printf(" time=%ld.%01ld ms", triptime/1000,
				       (triptime%1000)/100);
			else if (triptime >= 1000)
				printf(" time=%ld.%02ld ms", triptime/1000,
				       (triptime%1000)/10);
			else
				printf(" time=%ld.%03ld ms", triptime/1000,
				       triptime%1000);
		}
		if (dupflag)
			printf(" (DUP!)");
		if (csfailed)
			printf(" (BAD CHECKSUM!)");

		/* check the data */
		cp = ((u_char*)ptr) + sizeof(struct timeval);
		dp = &outpack[8 + sizeof(struct timeval)];
		for (i = sizeof(struct timeval); i < datalen; ++i, ++cp, ++dp) {
			if (*cp != *dp) {
				printf("\nwrong data byte #%d should be 0x%x but was 0x%x",
				       i, *dp, *cp);
				cp = (u_char*)ptr + sizeof(struct timeval);
				for (i = sizeof(struct timeval); i < datalen; ++i, ++cp) {
					if ((i % 32) == sizeof(struct timeval))
						printf("\n#%d\t", i);
					printf("%x ", *cp);
				}
				break;
			}
		}
	}
	return 0;
}

static long llsqrt(long long a)
{
	long long prev = ~((long long)1 << 63);
	long long x = a;

	if (x > 0) {
		while (x < prev) {
			prev = x;
			x = (x+(a/x))/2;
		}
	}

	return (long)x;
}

/*
 * finish --
 *	Print out statistics, and give up.
 */
void finish(void)
{
	struct timeval tv = cur_time;
	char *comma = "";

	tvsub(&tv, &start_time);

	putchar('\n');
	fflush(stdout);
	printf("--- %s ping statistics ---\n", hostname);
	printf("%ld packets transmitted, ", ntransmitted);
	printf("%ld received", nreceived);
	if (nrepeats)
		printf(", +%ld duplicates", nrepeats);
	if (nchecksum)
		printf(", +%ld corrupted", nchecksum);
	if (nerrors)
		printf(", +%ld errors", nerrors);
	if (ntransmitted) {
		printf(", %d%% packet loss",
		       (int) ((((long long)(ntransmitted - nreceived)) * 100) /
			      ntransmitted));
		printf(", time %ldms", 1000*tv.tv_sec+tv.tv_usec/1000);
	}
	putchar('\n');

	if (nreceived && timing) {
		long tmdev;

		tsum /= nreceived + nrepeats;
		tsum2 /= nreceived + nrepeats;
		tmdev = llsqrt(tsum2 - tsum * tsum);

		printf("rtt min/avg/max/mdev = %ld.%03ld/%lu.%03ld/%ld.%03ld/%ld.%03ld ms",
		       (long)tmin/1000, (long)tmin%1000,
		       (unsigned long)(tsum/1000), (long)(tsum%1000),
		       (long)tmax/1000, (long)tmax%1000,
		       (long)tmdev/1000, (long)tmdev%1000
		       );
		comma = ", ";
	}
	if (pipesize > 1) {
		printf("%spipe %d", comma, pipesize);
		comma = ", ";
	}
	if (ntransmitted > 1 && (!interval || (options&(F_FLOOD|F_ADAPTIVE)))) {
		int ipg = (1000000*(long long)tv.tv_sec+tv.tv_usec)/(ntransmitted-1);
		printf("%sipg/ewma %d.%03d/%d.%03d ms",
		       comma, ipg/1000, ipg%1000, rtt/8000, (rtt/8)%1000);
	}
	putchar('\n');
	exit(!nreceived || (deadline && nreceived < npackets));
}


void status(void)
{
	int loss = 0;
	long tavg = 0;

	status_snapshot = 0;

	if (ntransmitted)
		loss = (((long long)(ntransmitted - nreceived)) * 100) / ntransmitted;

	fprintf(stderr, "\r%ld/%ld packets, %d%% loss", ntransmitted, nreceived, loss);

	if (nreceived && timing) {
		tavg = tsum / (nreceived + nrepeats);

		fprintf(stderr, ", min/avg/ewma/max = %ld.%03ld/%lu.%03ld/%d.%03d/%ld.%03ld ms",
		       (long)tmin/1000, (long)tmin%1000,
		       tavg/1000, tavg%1000,
		       rtt/8000, (rtt/8)%1000,
		       (long)tmax/1000, (long)tmax%1000
		       );
	}
	fprintf(stderr, "\n");
}


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: "-w deadline" bug in ping/iputils- i will provide fix if you can tell me where owner of iputils is. Thanks.
  2012-01-09 17:26     ` Cloutier, Joseph (Joseph)
@ 2012-01-10  3:54       ` YOSHIFUJI Hideaki
  2012-01-10 18:00         ` [PATCH] iputils-s20101006.tar.bz2: "-w deadline" starts after "-c" xmitted, and "-c" was exceeded for flood ping Cloutier, Joseph (Joseph)
  0 siblings, 1 reply; 5+ messages in thread
From: YOSHIFUJI Hideaki @ 2012-01-10  3:54 UTC (permalink / raw)
  To: Cloutier, Joseph (Joseph)
  Cc: 'netdev@vger.kernel.org', YOSHIFUJI Hideaki,
	'Linus Torvalds'

Hello.

Cloutier, Joseph (Joseph) wrote:
> I have made a fix for the "-w deadline" issue to iputils-s20101006.tar.bz2.  There are 4 places in the code with the fix, identified by my name, Joe Cloutier- ALU.
>>
>>  There are 2 bugs fixed:
>>  *       For flood pings if the "-w" option is set then more pings than "-c x" are sent out.
>>  *       The "-w x" timer should be set after he last "-c x" ping is sent out.

Is this a real bug?

If both of -c COUNT and -w TIMEOUT are specified, ping exits by
timer _OR_ by the counter regardless of -f option.

If you want to ping really COUNT times, try -W TIMEOUT option.


... And please send your changes in the patch (or unified diff;
diff -u) format with your appropriate "sign-off" line, next time.


Thanks.

--yoshfuji

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH] iputils-s20101006.tar.bz2: "-w deadline" starts after "-c" xmitted, and "-c" was exceeded for flood ping
  2012-01-10  3:54       ` YOSHIFUJI Hideaki
@ 2012-01-10 18:00         ` Cloutier, Joseph (Joseph)
  0 siblings, 0 replies; 5+ messages in thread
From: Cloutier, Joseph (Joseph) @ 2012-01-10 18:00 UTC (permalink / raw)
  To: 'YOSHIFUJI Hideaki'
  Cc: 'netdev@vger.kernel.org', 'Linus Torvalds'

From: Joseph Cloutier <jcloutier@alcatel-lucent.com>

2 changes to ping & ping6.  Only ping_common.c affected.
  1- changed "-w deadline" to start deadline after "-c" pings have been transmitted, instead of from start of run.
  2- fixed bug where > "-c" pings are sent in flood ping mode when "-w deadline" option is also used.
Reason:
  Linux flood ping is an invaluable tool to finding duplex bugs, fiber problems, NE config problems-  especially
  when used to trouble shoot wireless system backhaul problems.  ANY dropped pings are red flag indicators.
  Current ping problem is that it terminates sometimes when outstanding pings are in transit, giving FALSE red
  flags.  Change "-w deadline" to start after last "-c" transmitted ping allows cleanup of stragglers.  Second fix is
  when "-f" option is running, "-c" is not rigorously checked when generating pings  A more rigorous check was
  added.

Signed-off-by: Joseph Cloutier <jcloutier@alcatel-lucent.com>

---
--- iputils-s20101006/ping_common.c.orig        2012-01-10 10:37:40.399719858 -0500
+++ iputils-s20101006/ping_common.c     2012-01-10 11:33:37.084662882 -0500
@@ -523,16 +523,6 @@ void setup(int icmp_sock)

        gettimeofday(&start_time, NULL);

-       if (deadline) {
-               struct itimerval it;
-
-               it.it_interval.tv_sec = 0;
-               it.it_interval.tv_usec = 0;
-               it.it_value.tv_sec = deadline;
-               it.it_value.tv_usec = 0;
-               setitimer(ITIMER_REAL, &it, NULL);
-       }
-
        if (isatty(STDOUT_FILENO)) {
                struct winsize w;

@@ -553,6 +543,7 @@ void main_loop(int icmp_sock, __u8 *pack
        int cc;
        int next;
        int polling;
+       int sig_deadline = 0;

        iov.iov_base = (char *)packet;

@@ -567,9 +558,22 @@ void main_loop(int icmp_sock, __u8 *pack
                /* Check for and do special actions. */
                if (status_snapshot)
                        status();
+               if((npackets == ntransmitted) && deadline &&
+                       (sig_deadline == 0)){
+                       sig_deadline++;
+                       struct itimerval it;
+
+                       it.it_interval.tv_sec = 0;
+                       it.it_interval.tv_usec = 0;
+                       it.it_value.tv_sec = deadline;
+                       it.it_value.tv_usec = 0;
+                       setitimer(ITIMER_REAL, &it, NULL);
+               }

                /* Send probes scheduled to this time. */
                do {
+                       if(npackets == ntransmitted)
+                               break;
                        next = pinger();
                        next = schedule_exit(next);
                } while (next <= 0);

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2012-01-10 18:01 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <7D3B6706FA74174B8C1AC24710890745136F1A0BF1@USNAVSXCHMBSA1.ndc.alcatel-lucent.com>
2012-01-04 20:56 ` "-w deadline" bug in ping/iputils- i will provide fix if you can tell me where owner of iputils is. Thanks Cloutier, Joseph (Joseph)
2012-01-09 15:45   ` YOSHIFUJI Hideaki
2012-01-09 17:26     ` Cloutier, Joseph (Joseph)
2012-01-10  3:54       ` YOSHIFUJI Hideaki
2012-01-10 18:00         ` [PATCH] iputils-s20101006.tar.bz2: "-w deadline" starts after "-c" xmitted, and "-c" was exceeded for flood ping Cloutier, Joseph (Joseph)

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).