All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: IPv4 kernel messages
       [not found] <Pine.LNX.4.03.9809070109140.24976-100000@mercator.cs.kuleuven.ac.be>
@ 1998-09-07  0:16 ` David S. Miller
  1998-09-07 14:47   ` Geert Uytterhoeven
  1998-09-07 15:10   ` Andrea Arcangeli
  0 siblings, 2 replies; 3+ messages in thread
From: David S. Miller @ 1998-09-07  0:16 UTC (permalink / raw)
  To: Geert.Uytterhoeven; +Cc: linux-kernel

   Date: 	Mon, 7 Sep 1998 01:12:16 +0200 (CEST)
   From: Geert Uytterhoeven <Geert.Uytterhoeven@cs.kuleuven.ac.be>

   They're still there:

   | Socket destroy delayed (r=0 w=160)
   | TCPv4 bad checksum from 10.0.24.8:0071 to 10.0.24.4:040c, len=20/20/40

   Are these just warnings to be disabled in 2.2, or is there something wrong?

   10.0.24.4 runs Linux/m68k 2.1.119. 10.0.24.8 is a PPC running vger-19980903.

I see them only rarely on my main workstation which talks a lot to the
rest of the world.  On my internal Linux-2.1.x machines I never see
it.

I would check out the csum routines on m68k and PPC to make sure they
are sane in all cases.

Here is the lifesaver development utility I have been using for a long
time to verify all major changes made to Sparc and MIPS checksumming
routines.  It won't work for you as-is, but you can figure out what it
is supposed to do and link the PPC and M68k csum routines into it to
perform verifications.  Note there is an ugly piece of MIPS inline asm
in here which you'll need to remove too as the last thing I used this
for was the Cobalt kernels :-)  Note it also performs performance
metrics on your code too, so it's useful for speed tuning as well as
verification.

/* cksum_helper.c: Lifesaver development utility.
 *
 * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
 */

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>

extern	int	gettimeofday();
extern	int	fprintf();

static struct timeval start_tv, stop_tv;

void
tvsub(tdiff, t1, t0)
	struct timeval *tdiff, *t1, *t0;
{
	tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
	tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
	if (tdiff->tv_usec < 0)
		tdiff->tv_sec--, tdiff->tv_usec += 1000000;
}

/*
 * Start timing now.
 */
void
start()
{
	(void) gettimeofday(&start_tv, (struct timezone *) 0);
}

/*
 * Stop timing and return real time in microseconds.
 */
unsigned long
stop()
{
	struct timeval tdiff;

	(void) gettimeofday(&stop_tv, (struct timezone *) 0);

	tvsub(&tdiff, &stop_tv, &start_tv);
	return (tdiff.tv_sec * 1000000 + tdiff.tv_usec);
}

void
micro(s, n)
	char	*s;
	int	n;
{
	struct timeval td;
	int	micro;

	tvsub(&td, &stop_tv, &start_tv);
	fprintf(stderr, "%s: %d secs\n", s, td.tv_sec);
	micro = td.tv_sec * 1000000 + td.tv_usec;
	fprintf(stderr, "%s: %d microseconds\n", s, micro / n);
}

void
milli(s, n)
	char	*s;
	int	n;
{
	struct timeval td;
	int	milli;

	tvsub(&td, &stop_tv, &start_tv);
	milli = td.tv_sec * 1000 + td.tv_usec / 1000;
	fprintf(stderr, "%s: %d milliseconds\n", s, milli / n);
}

/* Basically, we create buffers of varying sizes, feed them into
 * a known working checksum routine and the one to be tested,
 * if the test succeeds we just go on to the next buffer full of
 * random data and try again.  If it fails, the random data block
 * is written into files with unique names for each failure buffer,
 * and the two differing results go to stdout.
 */

/* What we test... */
extern unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
extern unsigned int csum_partial_copy(const char *src, char *dst, int len, int sum);
extern unsigned short ip_fast_csum(const unsigned char * iph, unsigned int ihl);
extern unsigned short int csum_tcpudp_magic(unsigned long saddr, unsigned long daddr,
					    unsigned short len, unsigned short proto,
					    unsigned int sum);
extern unsigned short ip_compute_csum(unsigned char * buff, int len);

typedef signed char s8;
typedef unsigned char u8;

typedef signed short s16;
typedef unsigned short u16;

typedef signed int s32;
typedef unsigned int u32;

typedef signed long long s64;
typedef unsigned long long u64;

/* Now the portable checksum routine we assume works on all machines. */
#define ADDCARRY(x)  (x > 65535 ? x -= 65535 : x)
#define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);}

int reference_cksum(u16 *w, int len)
{
	int sum = 0;
	int mlen = 0;
	int byte_swapped = 0;

	union {
		u8  c[2];
		u16 s;
	} s_util;
	union {
		u16 s[2];
		u32 l;
	} l_util;

	/* Force to even boundary. */
	if ((1 & (long) w) && (len > 0)) {
		REDUCE;
		sum <<= 8;
		s_util.c[0] = *(u8 *)w;
		w = (u16 *)((s8 *)w + 1);
		len--;
		byte_swapped = 1;
	}
	/* Unroll the loop to make overhead from
	 * branches &c small.
	 */
	while ((len -= 32) >= 0) {
		sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
		sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
		sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11];
		sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15];
		w += 16;
	}
	len += 32;
	while ((len -= 8) >= 0) {
		sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
		w += 4;
	}
	len += 8;
	if (len == 0 && byte_swapped == 0)
		goto fini;
	REDUCE;
	while ((len -= 2) >= 0) {
		sum += *w++;
	}
	if (byte_swapped) {
		REDUCE;
		sum <<= 8;
		byte_swapped = 0;
		if (len == -1) {
			s_util.c[1] = *(u8 *)w;
			sum += s_util.s;
			len = 0;
		} else
			len = -1;
	} else if (len == -1)
		s_util.c[0] = *(u8 *)w;
fini:
	if (len == -1) {
		/* Follow the standard (the odd byte may be shifted left
		 * by 8 bits or not as determined by endian-ness of the
		 * machine).
		 */
		s_util.c[1] = 0;
		sum += s_util.s;
	}
	REDUCE;
	return (~sum & 0xffff);
}

/* XXX */
static __inline__ unsigned short int csum_fold(unsigned int sum)
{
	__asm__("
	.set	noat            
	sll	$1,%0,16
	addu	%0,$1
	sltu	$1,%0,$1
	srl	%0,%0,16
	addu	%0,$1
	xori	%0,0xffff
	.set	at"
	: "=r" (sum)
	: "0" (sum)
	: "$1");

 	return sum;
}

static int filenum = 0;

struct iphdr {
	unsigned char	version:4,
  		        ihl:4;
	unsigned char	tos;
	unsigned short	tot_len;
	unsigned short	id;
	unsigned short	frag_off;
	unsigned char	ttl;
	unsigned char	protocol;
	unsigned short	check;
	unsigned int	saddr;
	unsigned int	daddr;
	/*The options start here. */
};

struct timeval random_seed;

static void verify_ip_fast_csum(void)
{
	struct iphdr **buffers;
	struct iphdr *this;
	int i, b, iters=512;
	u16 ctr=52;

	buffers = (struct iphdr **) malloc((sizeof(struct iphdr *)) * 512);
	if(!buffers)
		goto outofmem;
	for(i = 0; i < 512; i++) {
		this = (struct iphdr *) malloc((sizeof(struct iphdr)));
		if(!this)
			goto outofmem;
		buffers[i] = this;
	}
	gettimeofday(&random_seed, (struct timezone *) 0);
	srandom(random_seed.tv_usec);
	printf("verify_ip_fast_csum");
again:
	putchar('.');
	fflush(stdout);
	for(i = 0; i < 512; i++) {
		/* Fill with random bytes and zero csum field. */
		this = buffers[i];
		for(b = 0; b < (sizeof(struct iphdr)); b++)
			((u8 *)this)[b] = (random() >> 14) & 0xff;
		this->check = 0;
	}
	for(i = 0; i < 512; i++) {
		unsigned short csum, csum2;

		this = buffers[i];
		csum = ip_fast_csum((const unsigned char *)this, 5);
		csum2 = reference_cksum((u16 *)this, 20);
		if(csum != csum2) {
			printf("buffer %d gets bogus csum %04x (ref=<%04x>)!\n",
			       i, csum, csum2);
			exit(1);
		}
		this->check = csum;
		if((csum = ip_fast_csum((const unsigned char *)this, 5))) {
			printf("verify_ip_fast_csum: buffer %d gets bogus csum %04x!\n",
			       i, csum);
			exit(1);
		}
		if((csum2 = reference_cksum((u16 *)this, 20))) {
			printf("verify_ip_fast_csum: buffer %d gets bogus csum2 %04x!\n",
			       i, csum2);
			exit(1);
		}
	}
	if(--iters > 0)
		goto again;
	printf("done\n");
	fflush(stdout);
	for(i = 0; i < 512; i++)
		free(buffers[i]);
	free(buffers);
	return;

outofmem:
	printf("Out of memory in verify_ip_fast_csum!\n");
	exit(1);
}

static char compare_buffer[2048];

static void verify_csum_partial(void)
{
	int *sizes;
	struct iphdr **buffers;
	struct iphdr *this;
	int i, b, iters=512;
	u16 ctr=62;

	buffers = (struct iphdr **) malloc((sizeof(struct iphdr *)) * 512);
	sizes = (int *) malloc(sizeof(int) * 512);
	if(!buffers)
		goto outofmem;
	printf("verify_csum_partial");
	gettimeofday(&random_seed, (struct timezone *) 0);
	srandom(random_seed.tv_usec);
again:
	for(i = 0; i < 512; i++) {
		int sz;

		sz = random() & 0x7ff;
		if(sz > 1500) sz=1500;
		if(sz < sizeof(struct iphdr)) sz=sizeof(struct iphdr);

		sizes[i] = sz;
		this = (struct iphdr *) malloc(sz);
		if(!this)
			goto outofmem;
		buffers[i] = this;
	}
	putchar('.');
	fflush(stdout);
	for(i = 0; i < 512; i++) {
		/* Fill with random bytes and zero csum field. */
		this = buffers[i];
		for(b = 0; b < sizes[i]; b++)
			((u8 *)this)[b] = (random() >> 14) & 0xff;
		this->check = 0;
	}
	for(i = 0; i < 512; i++) {
		u32 lcsum;
		unsigned short csum, csum2;

		this = buffers[i];
		lcsum = csum_partial(((const unsigned char *)this)+2, sizes[i], 0);
		csum2 = reference_cksum(((u16 *)this)+1, sizes[i]);
		csum = csum_fold(lcsum);
		if(csum != csum2) {
			u16 *ptr = (u16 *) this;

			printf("csum_partial: buffer %d gets bogus "
			       "csum %04x (ref=<%04x>)!\n",
			       i, csum, csum2);
			printf("csum_partial: buffer dump lngth=%d\n", sizes[i]);
			for(b = 0; b < sizes[i]/2; b++) {
				printf("[%04x]\n", ((u16 *)this)[b]);
			}
			printf("\n");
			exit(1);
		}

		this->check = csum;
		if((csum = csum_fold(csum_partial(((const unsigned char *)this)+2,
						  sizes[i], 0)))) {
			printf("verify_csum_partial: buffer %d gets bogus csum %04x!\n",
			       i, csum);
			exit(1);
		}
		if((csum2 = reference_cksum(((u16 *)this)+1, sizes[i]))) {
			printf("verify_csum_partial: buffer %d gets bogus csum2 %04x!\n",
			       i, csum2);
			exit(1);
		}
	}
	for(i=0; i<512; i++)
		free(buffers[i]);
	if(--iters > 0)
		goto again;
	printf("done\n");
	fflush(stdout);
	free(buffers);
	return;

outofmem:
	printf("Out of memory in verify_csum_partial!\n");
	exit(1);
}

static void verify_csum_partial_cunaligned(void)
{
	int *sizes;
	struct iphdr **buffers;
	struct iphdr *this;
	int i, b, iters=512;
	u16 ctr=62;

	buffers = (struct iphdr **) malloc((sizeof(struct iphdr *)) * 512);
	sizes = (int *) malloc(sizeof(int) * 512);
	if(!buffers)
		goto outofmem;
	printf("verify_csum_partial");
	gettimeofday(&random_seed, (struct timezone *) 0);
	srandom(random_seed.tv_usec);
again:
	for(i = 0; i < 512; i++) {
		int sz;

#if 0
		sz = random() & 0x7ff;
		if(sz > 1500) sz=1500;
		if(sz < sizeof(struct iphdr)) sz=sizeof(struct iphdr);
#else
		sz = 11;
#endif
		sizes[i] = sz;
		this = (struct iphdr *) malloc(sz);
		if(!this)
			goto outofmem;
		buffers[i] = this;
	}
	putchar('.');
	fflush(stdout);
	for(i = 0; i < 512; i++) {
		/* Fill with random bytes and zero csum field. */
		this = buffers[i];
		for(b = 0; b < sizes[i]; b++)
			((u8 *)this)[b] = (random() >> 14) & 0xff;
		this->check = 0;
	}
	for(i = 0; i < 512; i++) {
		u32 lcsum;
		unsigned short csum, csum2;

		this = buffers[i];
		lcsum = csum_partial_copy(((const unsigned char *)this) + 2,
					  compare_buffer, sizes[i], 0);
		csum2 = reference_cksum((((u16 *)this)+1), sizes[i]);
		csum = csum_fold(lcsum);
		if(csum != csum2) {
			u16 *ptr = (u16 *) this;

			printf("csum_partial: buffer %d gets bogus "
			       "csum %04x (ref=<%04x>)!\n",
			       i, csum, csum2);
			printf("csum_partial: buffer dump lngth=%d\n", sizes[i]);
			for(b = 0; b < sizes[i]/2; b++) {
				printf("[%04x]\n", ((u16 *)this)[b]);
			}
			printf("\n");
			exit(1);
		}
		this->check = csum;
		if((csum = csum_fold(csum_partial_copy(((const unsigned char *)this) + 2,
						  compare_buffer, sizes[i], 0)))) {
			printf("verify_csum_partial: buffer %d gets bogus csum %04x!\n",
			       i, csum);
			exit(1);
		}
		if((csum2 = reference_cksum((((u16 *)this)+1), sizes[i]))) {
			printf("verify_csum_partial: buffer %d gets bogus csum2 %04x!\n",
			       i, csum2);
			exit(1);
		}
	}
	for(i=0; i<512; i++)
		free(buffers[i]);
	if(--iters > 0)
		goto again;
	printf("done\n");
	fflush(stdout);
	free(buffers);
	return;

outofmem:
	printf("Out of memory in verify_csum_partial!\n");
	exit(1);
}

static void verify_csum_partial_copy(void)
{
	int *sizes;
	struct iphdr **buffers;
	struct iphdr *this;
	char *dst = compare_buffer;
	int i, b, iters=512;
	u16 ctr=62;

	buffers = (struct iphdr **) malloc((sizeof(struct iphdr *)) * 512);
	sizes = (int *) malloc(sizeof(int) * 512);
	if(!buffers)
		goto outofmem;
	printf("verify_csum_partial_copy");
	gettimeofday(&random_seed, (struct timezone *) 0);
	srandom(random_seed.tv_usec);
again:
	for(i = 0; i < 512; i++) {
		int sz;

		sz = random() & 0x7ff;
		if(sz > 1500) sz=1500;
		if(sz < sizeof(struct iphdr)) sz=sizeof(struct iphdr);
		sizes[i] = sz;
		this = (struct iphdr *) malloc(sz);
		if(!this)
			goto outofmem;
		buffers[i] = this;
	}
	putchar('.');
	fflush(stdout);
	for(i = 0; i < 512; i++) {
		/* Fill with random bytes and zero csum field. */
		this = buffers[i];
		for(b = 0; b < sizes[i]; b++)
			((u8 *)this)[b] = (random() >> 14) & 0xff;
		this->check = 0;
	}
	for(i = 0; i < 512; i++) {
		u32 lcsum;
		unsigned short csum, csum2;

		this = buffers[i];
		lcsum = csum_partial_copy((const unsigned char *)this, dst, sizes[i], 0);
		csum2 = reference_cksum((u16 *)this, sizes[i]);
		if(memcmp(this, dst, sizes[i])) {
			printf("csum_partial_copy: buffer %d mismatch after copy!\n", i);
		}
		csum = csum_fold(lcsum);
		if(csum != csum2) {
			u16 *ptr = (u16 *) this;

			printf("csum_partial_copy: buffer %d gets bogus "
			       "csum %04x (ref=<%04x>)!\n",
			       i, csum, csum2);
			printf("csum_partial_copy: buffer dump lngth=%d\n", sizes[i]);
#if 0
			for(b = 0; b < sizes[i]/2; b++) {
				printf("[%04x]\n", ((u16 *)this)[b]);
			}
			printf("\n");
#endif
			exit(1);
		}
		this->check = csum;
		if((csum = csum_fold(csum_partial_copy((const unsigned char *)this,
						       dst, sizes[i], 0)))) {
			printf("verify_csum_partial_copy: buffer %d gets bogus "
			       "csum %04x!\n",
			       i, csum);
			exit(1);
		}
		if((csum2 = reference_cksum((u16 *)this, sizes[i]))) {
			printf("verify_csum_partial_copy: buffer %d gets bogus "
			       "csum2 %04x!\n",
			       i, csum2);
			exit(1);
		}
	}
	for(i=0; i<512; i++)
		free(buffers[i]);
	if(--iters > 0)
		goto again;
	printf("done\n");
	fflush(stdout);
	free(buffers);
	return;

outofmem:
	printf("Out of memory in verify_csum_partial_copy!\n");
	exit(1);
}

#define N 10000

static void measure_ip_fast_csum(void)
{
	struct iphdr **buffers;
	struct iphdr *this;
	int i, b, iters=512;
	int clock;
	u16 ctr=52;

	buffers = (struct iphdr **) malloc((sizeof(struct iphdr *)) * 512);
	if(!buffers)
		goto outofmem;
	for(i = 0; i < 512; i++) {
		this = (struct iphdr *) malloc((sizeof(struct iphdr)));
		if(!this)
			goto outofmem;
		buffers[i] = this;
	}
	gettimeofday(&random_seed, (struct timezone *) 0);
	srandom(random_seed.tv_usec);
	printf("measure_ip_fast_csum...");
	fflush(stdout);
	for(i = 0; i < 512; i++) {
		/* Fill with random bytes and zero csum field. */
		this = buffers[i];
		for(b = 0; b < (sizeof(struct iphdr)); b++)
			((u8 *)this)[b] = (random() >> 14) & 0xff;
		this->check = 0;
	}
	start();
	for(b = 0; b < N; b++) {
		for(i = 0; i < 512; i++) {
			this = buffers[i];
			ip_fast_csum((const unsigned char *)this, 5);
		}
	}
	clock = stop();
	printf("done\n");
	fflush(stdout);
	printf("ip_fast_csum: %d iterations takes %ld microseconds\n", N, clock);
	clock = clock/N;
	printf("ip_fast_csum: 1 iteration takes <%ld microseconds>==", clock);
	clock = (int)((double)(((double)clock) / ((double)512.00)) * (double)100.00);
	printf("<%ld nanoseconds>\n", clock);
	for(i = 0; i < 512; i++)
		free(buffers[i]);
	free(buffers);
	return;

outofmem:
	printf("Out of memory in measure_ip_fast_csum!\n");
	exit(1);
}

#define NBUFS 256

static void measure_csum_partial(void)
{
	int *sizes;
	struct iphdr **buffers;
	struct iphdr *this;
	int i, b, iter;
	u16 ctr=62;

	buffers = (struct iphdr **) malloc((sizeof(struct iphdr *)) * NBUFS);
	sizes = (int *) malloc(sizeof(int) * NBUFS);
	if(!buffers)
		goto outofmem;
	printf("measure_csum_partial\n");
	gettimeofday(&random_seed, (struct timezone *) 0);
	srandom(random_seed.tv_usec);
	for(i = 0; i < NBUFS; i++) {
		int sz;

		/* sz = (i + sizeof(struct iphdr)); */
		sz = ((i+1) * 1024);
		/* sz = ((i+32)); */
		sizes[i] = sz;
		this = (struct iphdr *) malloc(sz);
		if(!this)
			goto outofmem;
		buffers[i] = this;
	}
	for(i = 0; i < NBUFS; i++) {
		/* Fill with random bytes and zero csum field. */
		this = buffers[i];
		for(b = 0; b < sizes[i]; b++)
			((u8 *)this)[b] = (random() >> 14) & 0xff;
		this->check = 0;
	}
	for(b = 0; b < NBUFS; b++) {
		int clock, sz;
		const unsigned char *thing;

		sz = sizes[b];
		thing = (const unsigned char *) buffers[b];
		start();
		for(iter=0; iter < N; iter++) {
			for(i = 0; i < 512; i++) {
				csum_partial(thing, sz, 0);
			}
		}
		clock = stop();
		printf("csum_partial: sz[%d] %d iterations takes %ld microseconds\n",
		       sz, N, clock);
		clock = clock/N;
		printf("csum_partial: sz[%d] 1 iteration takes <%ld microseconds>==",
		       sz, clock);
		clock = (int)((double)(((double)clock) /
				       ((double)512.00)) * (double)100.00);
		printf("<%ld nanoseconds>\n", clock);
		fflush(stdout);
	}
	for(i=0; i<NBUFS; i++)
		free(buffers[i]);
	free(buffers);
	return;

outofmem:
	printf("Out of memory in measure_csum_partial!\n");
	exit(1);
}

static void measure_csum_partial_copy(void)
{
	int *sizes;
	struct iphdr **buffers;
	struct iphdr *this;
	char *dst;
	int i, b, iter;
	int sz;
	u16 ctr=62;

	buffers = (struct iphdr **) malloc((sizeof(struct iphdr *)) * NBUFS);
	sizes = (int *) malloc(sizeof(int) * NBUFS);
	if(!buffers)
		goto outofmem;
	printf("measure_csum_partial_copy\n");
	gettimeofday(&random_seed, (struct timezone *) 0);
	srandom(random_seed.tv_usec);
	for(i = 0; i < NBUFS; i++) {
		/* sz = (i + sizeof(struct iphdr)); */
	        /* sz = ((i+1) * 0x80); */
		/* sz = ((i+32)); */
		sz = (1024 * 1024);
		sizes[i] = sz;
		this = (struct iphdr *) malloc(sz);
		if(!this)
			goto outofmem;
		buffers[i] = this;
	}
	dst = (char *) malloc(sz + 1024);
	for(i = 0; i < NBUFS; i++) {
		/* Fill with random bytes and zero csum field. */
		this = buffers[i];
		for(b = 0; b < sizes[i]; b++)
			((u8 *)this)[b] = (random() >> 14) & 0xff;
		this->check = 0;
	}
	for(b = 0; b < NBUFS; b++) {
		int clock, sz;
		const unsigned char *thing;

		sz = sizes[b];
		thing = (const unsigned char *) buffers[b];
		start();
		for(iter=0; iter < N; iter++) {
			for(i = 0; i < 512; i++) {
				csum_partial_copy(thing, dst, sz, 0);
			}
		}
		clock = stop();
		printf("csum_partial_copy: sz[%d] %d iterations takes %ld "
		       "microseconds\n",
		       sz, N, clock);
		clock = clock/N;
		printf("csum_partial_copy: sz[%d] 1 iteration takes <%ld "
		       "microseconds>==",
		       sz, clock);
		clock = (int)((double)(((double)clock) /
				       ((double)512.00)) * (double)100.00);
		printf("<%ld nanoseconds>\n", clock);
		fflush(stdout);
	}
	for(i=0; i<NBUFS; i++)
		free(buffers[i]);
	free(buffers);
	return;

outofmem:
	printf("Out of memory in measure_csum_partial_copy!\n");
	exit(1);
}

void main(int argc, char **argv)
{
	verify_csum_partial();
#if 0
	verify_csum_partial_copy();
	verify_csum_partial_cunaligned();
	verify_ip_fast_csum();
	measure_csum_partial();
	measure_csum_partial_copy();
	/* measure_ip_fast_csum(); */
#endif
	exit(0);
}

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/faq.html

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

* Re: IPv4 kernel messages
  1998-09-07  0:16 ` IPv4 kernel messages David S. Miller
@ 1998-09-07 14:47   ` Geert Uytterhoeven
  1998-09-07 15:10   ` Andrea Arcangeli
  1 sibling, 0 replies; 3+ messages in thread
From: Geert Uytterhoeven @ 1998-09-07 14:47 UTC (permalink / raw)
  To: David S. Miller, Ulrik De Bie; +Cc: Linux kernel, Linux/m68k

On Sun, 6 Sep 1998, David S. Miller wrote:
>    Date: 	Mon, 7 Sep 1998 01:12:16 +0200 (CEST)
>    From: Geert Uytterhoeven <Geert.Uytterhoeven@cs.kuleuven.ac.be>
> 
>    They're still there:
> 
>    | Socket destroy delayed (r=0 w=160)
>    | TCPv4 bad checksum from 10.0.24.8:0071 to 10.0.24.4:040c, len=20/20/40
> 
>    Are these just warnings to be disabled in 2.2, or is there something wrong?
> 
>    10.0.24.4 runs Linux/m68k 2.1.119. 10.0.24.8 is a PPC running vger-19980903.
> I see them only rarely on my main workstation which talks a lot to the
> rest of the world.  On my internal Linux-2.1.x machines I never see
> it.
> 
> I would check out the csum routines on m68k and PPC to make sure they
> are sane in all cases.
> 
> Here is the lifesaver development utility I have been using for a long
> time to verify all major changes made to Sparc and MIPS checksumming
> routines.  It won't work for you as-is, but you can figure out what it
> is supposed to do and link the PPC and M68k csum routines into it to
> perform verifications.  Note there is an ugly piece of MIPS inline asm
> in here which you'll need to remove too as the last thing I used this
> for was the Cobalt kernels :-)  Note it also performs performance
> metrics on your code too, so it's useful for speed tuning as well as
> verification.

Thanks! The PPC checksumming code passed the test, but the m68k code seems to
be broken. I got:

    verify_ip_fast_csum: buffer 0 gets bogus csum abe7!

Ulrik De Bie wrote:
> I think the following information is interesting here. I have the same with
> Linux/i486 running recent-vger and PPC running recent-vger.
> 
> So both intel and m68k are wrong, or ppc is wrong. Which would give a big
> hint to the latter.

Since PPC passed the test, this would indicate that ia32 is incorrect, too.

But if I understand it correctly, the test isn't exhaustive, right?

Greetings,

						Geert

P.S. I put the code I used (i.e. Dave's with adaptations for ppc and m68k) on
     my webpage: http://www.cs.kuleuven.ac.be/~geert/bin/cksum_helper.c
--
Geert Uytterhoeven                     Geert.Uytterhoeven@cs.kuleuven.ac.be
Wavelets, Linux/{m68k~Amiga,PPC~CHRP}  http://www.cs.kuleuven.ac.be/~geert/
Department of Computer Science -- Katholieke Universiteit Leuven -- Belgium


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/faq.html

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

* Re: IPv4 kernel messages
  1998-09-07  0:16 ` IPv4 kernel messages David S. Miller
  1998-09-07 14:47   ` Geert Uytterhoeven
@ 1998-09-07 15:10   ` Andrea Arcangeli
  1 sibling, 0 replies; 3+ messages in thread
From: Andrea Arcangeli @ 1998-09-07 15:10 UTC (permalink / raw)
  To: David S. Miller; +Cc: Geert.Uytterhoeven, linux-kernel

On Sun, 6 Sep 1998, David S. Miller wrote:

>Here is the lifesaver development utility I have been using for a long

Cool! ;-)

>time to verify all major changes made to Sparc and MIPS checksumming
>routines.  It won't work for you as-is, but you can figure out what it
>is supposed to do and link the PPC and M68k csum routines into it to
>perform verifications.  Note there is an ugly piece of MIPS inline asm
>in here which you'll need to remove too as the last thing I used this
>for was the Cobalt kernels :-)  Note it also performs performance

The asm looks wrong.

>/* XXX */
>static __inline__ unsigned short int csum_fold(unsigned int sum)
>{
>	__asm__("
>	.set	noat            
>	sll	$1,%0,16
>	addu	%0,$1
>	sltu	$1,%0,$1
        ^^^^^^^^^^^^^^^^

With my MIPS emulator sltu do soemthing like "<" C operator, $1 return
only 0 or 1 and so the asm seems far from what csum_fold should do (I
emulated the asm in C and does not work).

Here my C implementation of csum_fold() that seems to work with the
csum_partial() in the current arch/i386/lib/checksum.c.

--- cksum_helper.c.orig	Mon Sep  7 14:51:25 1998
+++ cksum_helper.c	Mon Sep  7 17:17:24 1998
@@ -180,6 +180,15 @@
 /* XXX */
 static __inline__ unsigned short int csum_fold(unsigned int sum)
 {
+#ifndef __mips__ /* or better #ifndef buggy ;-) */
+	union {
+		u16 s[2];
+		u32 l;
+	} l_util;
+	
+	REDUCE;
+	return ~sum & 0xffff;
+#else
 	__asm__("
 	.set	noat            
 	sll	$1,%0,16
@@ -194,6 +203,7 @@
 	: "$1");
 
  	return sum;
+#endif
 }
 
 static int filenum = 0;
@@ -215,6 +225,7 @@
 
 struct timeval random_seed;
 
+#if 0
 static void verify_ip_fast_csum(void)
 {
 	struct iphdr **buffers;
@@ -280,6 +291,7 @@
 	printf("Out of memory in verify_ip_fast_csum!\n");
 	exit(1);
 }
+#endif
 
 static char compare_buffer[2048];
 
@@ -555,6 +567,7 @@
 
 #define N 10000
 
+#if 0
 static void measure_ip_fast_csum(void)
 {
 	struct iphdr **buffers;
@@ -607,6 +620,7 @@
 	printf("Out of memory in measure_ip_fast_csum!\n");
 	exit(1);
 }
+#endif
 
 #define NBUFS 256
 
@@ -748,7 +762,7 @@
 	exit(1);
 }
 
-void main(int argc, char **argv)
+int main(int argc, char **argv)
 {
 	verify_csum_partial();
 #if 0

Andrea[s] Arcangeli


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/faq.html

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

end of thread, other threads:[~1998-09-07 13:26 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <Pine.LNX.4.03.9809070109140.24976-100000@mercator.cs.kuleuven.ac.be>
1998-09-07  0:16 ` IPv4 kernel messages David S. Miller
1998-09-07 14:47   ` Geert Uytterhoeven
1998-09-07 15:10   ` Andrea Arcangeli

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.