From: Al Viro <[EMAIL PROTECTED]>
Date: Sat, 7 Jan 2006 08:44:42 +0000

[ BTW Al, I noticed you subscribed to netdev, you don't need to
  do that if all you want to do is make a posting and be involved
  in that particular discussion.  If you really are interested in
  everything else that goes on here, that's fine too :-) ]

>       BTW, why does csum_tcpudp_nofold() have such a prototype?

Historic baggage...

> The value we are interested in is 8bit;  all callers
> pass either an explicit constant smaller than 256 or iphdr ->protocol
> (__u8).  Moreover, in any arithmetics both __u8 and __u16 will be
> promoted to the same thing, so even arguments about avoiding casts
> in the function body do not apply...

Agreed.

>       Even funnier, prototype depends on target; amd64 csum_tcpudp_nofold()
> takes unsigned saddr, unsigned daddr; alpha has both unsigned long...
> At the same time, amd64 has
> static inline unsigned short int 
> csum_tcpudp_magic(unsigned long saddr, unsigned long daddr,
>                   unsigned short len, unsigned short proto, unsigned int sum) 
> {
>         return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
> }
> so we pass 32bit value to that puppy as 64bit argument, only to cut it
> back to 32bit when we pass it to csum_tcpudp_nofold()...

Arch specific typing is bad for these interfaces... But, one thing.
Richard Henderson and I always talked about keeping around a 64-bit
running checksum on 64-bit platforms so we didn't need to fold
the values so many times while building a packet.  However, this idea
never materialized, so currently all platforms should bascially be
using the same types.

>       That's one hell of a hot path, so I'd rather avoid messing with
> it without a very good idea of what's going on.  One guaranteed-to-be-safe
> way of annotating it is
> #define csum_tcp_magic(saddr, daddr, len, proto, sum) \
>       csum_tcp_magic((__force u32)(__be32)saddr, (__force u32)(__be32)daddr,\
>                      len, proto, sum)
> which would verify that arguments have the right types and have those casts
> leave the generated code as-is - actual arguments _are_ unsigned int from
> C point of view, so those casts will leave arguments as-is.

Not beautiful, but functional...

>       The thing is, for smaller-than-int bitwise types (e.g. __be16)
> ~ is a prohibited operation.  The reason is simple: integer promotion
> happens before ~, so we are guaranteed that value of ~x will _not_
> be within range of our type.  I can try to teach sparse about such
> "slightly fouled" __be16, so that conversion back to our type (e.g.
> from assignment) would go without complaints, but there are some limits
> to that.

Why not just make some kind of "negate()" macro that hides away all of
the typing issues?  Another way to describe the operation is as a
xor of X with an all-1's bitmask the same size of X.  Maybe that helps
describe it better?

> Note that some places around checksum handling *WILL* give complaints,
> no matter how smart sparse might become.  When we stuff big-endian
> 16bit values or ~ of such values into u32 array and calculate checksum
> of that, we rely on the fact that both all-0 and all-1 16bit words _and_
> any reordering of words do not affect the checksum, which is far beyond
> anything sparse could be expected to understand.  For places like that
> (mostly in netfilter code) a forced cast and comment explaining what's
> going on and what we are relying upon would be the right thing, IMO.
> No need to reproduce the entire RFC1071, but reference to it would not be
> a bad thing either...

Indeed.
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to