----- Original Message -----
From: "Harald Welte" <[EMAIL PROTECTED]>
To: "Bart De Schuymer" <[EMAIL PROTECTED]>
Cc: "Netfilter Development Mailinglist" <[EMAIL PROTECTED]>
Sent: Friday, March 15, 2002 11:01 PM
Subject: Re: iptables on sparc64 platform?


> I don't have a very clear view on the user32/kernel64 issue on sparclinux
> either, sorry.
>
> I haven't done any hacking on that platform yet, so don't expect any
> explanation or help from me ;)
>
> On the other hand, I would gladly appreciate any pointers to information
> on what precicely the issues are.

The only issue I see is the kernel-userspace communication. If userspace and
kernel use the same header file to describe their communication structs
(like struct ipt_replace) one has to make sure they use the same size.
On a sparc64 an unsigned int for the kernel is 64 bits, for userspace it's
32 bits. What one can do is make __u32 of all the unsigned ints (and all
other types who's size is machine dependent), __u32 is garanteed to be 32
bits. Now, this makes it silly for a 64 bit kernel, as it will be using only
32 bits. Using __u64 instead seems worse to me, because then a 32 bit kernel
has to go calculate with 64 bits, must be slower.

Even worse is when one wants to use pointers in the communication structs.
Lucky me wants to do this. Iptables is unlucky too, struct ipt_replace has a
"struct ipt_counters *counters" member.
A pointer in the sparc64 kernel is 64 bits long while it's 32 bits long in
32 bit userspace. The solution is to always make an __u64 out of a pointer
and make a pointer out of the __u64.
Userspace can use the following 2 functions for that:
__u64 ptr2int(void *x)
{
    if (sizeof(void *) == 4)
        return (((__u64)(__u32)x) & (0x00000000ffffffffL));
    else
        return ((__64)x);
}
void * int2ptr(__u64 x)
{
    if (sizeof(void *) == 4)
        return ((void *)(__u32)x);
    else
        return ((void *)x);
}

The kernel uses the following:
#if BITS_PER_LONG == 64
#define int2ptr(x) ((void *)x)
#else
#define int2ptr(x) ((void *)(u32)x)
#endif

(the kernel doesn't need to convert pointers to __u64, userspace is nothing
with kernel pointers)
When compiling the userspace tool, it gives 2 warnings for those 2 functions
on my Normal Architecture:
warning: cast from pointer to integer of different size
warning: cast to pointer from integer of different size

I am very allergic to warnings.
Even if I could get these warnings to go away, fact remains it is ugly like
hell.

So, as iptables does not do any of these things and I heard it works on the
Sparc64 (only rumours) I am very interested in knowing how this is done.
I am probably going to remove support for these special architectures with
different sizes for userspace and kernel (there are others, like ppc64,
mips64 and hppa64) if it has to be done the ugly way. It is just, well, too
ugly...

cheers,
Bart



Reply via email to