Re: ia32 ip checksum optimizations

Andrea Arcangeli (andrea@suse.de)
Wed, 26 May 1999 18:31:24 +0200 (CEST)


On Wed, 26 May 1999, Artur Skawina wrote:

>(1) the checksum is defined in terms of 16bit words - it might have
> some 'wonderful properties', but being able to directly compute it
> from half of every word isn't one of them :)

The checksum of one byte is done padding the odd byte with a virtual byte
set to zero.

The lenght of the checksum has nothing to do with the alignment of the
buffer.

I don't follow you here.

>(2) if kmalloc starts returning unaligned blocks we're in trouble
> anyway

Where?? I am writing this while I am having an high network load with this
applyed (+ my previous csum patch) and everything works _fine_ as without
the patch.

Index: linux/mm/slab.c
===================================================================
RCS file: /var/cvs/linux/mm/slab.c,v
retrieving revision 1.1.2.6
diff -u -r1.1.2.6 slab.c
--- linux/mm/slab.c 1999/05/13 19:49:25 1.1.2.6
+++ linux/mm/slab.c 1999/05/26 16:15:27
@@ -1688,10 +1688,25 @@
{
cache_sizes_t *csizep = cache_sizes;

+#if 0
for (; csizep->cs_size; csizep++) {
if (size > csizep->cs_size)
continue;
return __kmem_cache_alloc(csizep->cs_cachep, flags);
+#else
+ size++;
+ for (; csizep->cs_size; csizep++) {
+ if (size > csizep->cs_size)
+ continue;
+ {
+ char * m;
+ m = (char *) __kmem_cache_alloc(csizep->cs_cachep,
+ flags);
+ if (!m)
+ return NULL;
+ return m+1;
+ }
+#endif
}
printk(KERN_ERR "kmalloc: Size (%lu) too large\n", (unsigned long) size);
return NULL;
@@ -1705,6 +1720,9 @@

if (!objp)
goto null_ptr;
+#if 1
+ objp = (void *)((unsigned long) objp - 1);
+#endif
nr = MAP_NR(objp);
if (nr >= max_mapnr)
goto bad_ptr;
@@ -1750,6 +1768,9 @@

if (!objp)
goto null_ptr;
+#if 1
+ objp = (void *)((unsigned long) objp - 1);
+#endif
nr = MAP_NR(objp);
if (nr >= max_mapnr)
goto null_ptr;

>(3) it's the IP checksum

The alignment of the skb->data has _nothing_ to do with TCP/IP. If you
start odd will finish odd and you'll still have a valid IP packet.

>Unless you start checksumming with an odd address [1], buf&1==0.
>
>[1] and this can't happen unless either (a) mem allocation routines
> start returning unaligned memory, or (b) you keep partial buffers
> stored at odd addresses.

(a) is sure not going to be become true in the future.

But you missed (c):

(c) you do something like what tunnelling does, but you'll store a not
32byte aligned information in the hard-header of the skb.

>> >the <686 csum_partial_copy_generic already does align the destination.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>>
>> Where?? The only time %edi is changed is after every unrolled loop where
>> is incremented of 64 bytes.
>
>look again

Looked _again_ and I think to have guessed what you was talking about:

#if CPU!=686
-------^^---
[..]
testl $2, %edi # Check alignment.
jz 2f # Jump if alignment is ok.
[..]

That's __not__ the _686_ checksum (and btw the above is _not_ a 32bit or a
16bit alignemnt check since the last LSB can still be 0 or 1). And
aligning %edi is going to be useless there too because %edi is going to be
32bit aligned all the time.

This doesn't mean that the buffer will be _always_ 32bit aligned.
According to me the csum_partial is allowed to go slow like h*ell if the
buffer is not 32bit aligned but it must _not_ left open doors for buffer
overflows.

>> >Now, with the alignment issue behind, how about concentrating
>>
>> Do I convinced you that we shouldn't rely on the %esi 16bit alignement?
>
>of course, not. [1]
>
>[1] and btw this assumption (buf%1==0) is present in almost every
> architecture. I didn't look if they used similar tricks to avoid
> the branches though :)

You must make difference if they suppose `buf%1 == 0' in order to make
some assumption to go faster in the case that `buf%1 == 0' is true. That's
the common case of course. I completly agree to optimize the code by
supposing that the condition `buf%1 == 0' will be true. I proposed this
way in first place.

I only don't agree with having a potentian buffer overflow if `buf%1 == 0'
is true.

Andrea Arcangeli

(Still running fine with `kmalloc()&1==1' :-).

-
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/