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