Re: [mpls-linux-general] Endianess and bitfields
Status: Beta
Brought to you by:
jleu
|
From: James R. L. <jl...@mi...> - 2002-10-30 02:19:39
|
Hello,
When I first heard of people trying to run mpls-linux on PPC the first
thing I though about was byte-ordering issues with these keys. After
thinking about it for a long time, it turns out that there is no need
to worry. Since the keys are only used inside the kernel and never
undergo a net-host or host-net conversion, it doesn't matter what the
resulting bit layout of the key is. mpls-linux uses all 32bits to store
it in the radix tree. The only thing that matters is that the value
is unique, which it is no matter what byte ordering we are dealing with.
ldp-portable has to deal with this quite a bit. Look in
ldp-portable/lib/ldp_nortel.h and you will see many example of preservation
of bit ordering in a bitfield.
On Tue, Oct 29, 2002 at 10:03:27PM +0100, Georg Klug wrote:
> Hi all,
>
> today I was wrestling with some endian issues in the MPLS kernel patch.
> Especially the following bitfield definition is interesting:
>
> struct mpls_gen_key {
> unsigned int index:10;
> unsigned int gen:20;
> unsigned int type:2;
> };
>
> The C language does not define exactly how these bits are stored into
> memory. It might either be right-to-left assigned or left-to-right
> assigned depending on the machine or even on the compiler used. So using
> this kind of struct is not portable in general. But looking into the
> kernel sources there are also such structure definitions (i.e. struct iphdr
> in include/linux/ip.h where the first byte of the ip header is defined as
> a bitfield).
>
> Anyway gcc on powerpc uses left-to-right assigned bit-fields, which
> causes the struct above not to work correctly on powerpc.
>
> Here is what the struct would look like on powerpc machines:
>
> Byte 0 Byte 1 Byte 2 Byte 3
> 76543210 76543210 76543210 76543210
> | index || ----------- gen -------|||< (last 2 bits are type)
>
> On the little endian x86 architecture with right-to-left assigned bit-
> fields the struct look like:
>
> Byte 0 Byte 1 Byte 2 Byte 3
> 76543210 76543210 76543210 76543210
> |in-lo | |g-lo||| | g-mid| |||g-hi|
>
> So the original fields are stored as follows:
> index: Byte1[Bits 1-0] Byte0[Bits 7-0]
> gen: Byte3[Bits 5-0] Byte2[Bits 7-0] Byte1[Bits 7-2]
> type Byte3[Bits 7-6]
>
> This looks rather complex but after byte swapping which must be applied
> on little-endian machines before sending the data on the wire it looks
> as follows:
>
> Byte 0 Byte 1 Byte 2 Byte 3
> 76543210 76543210 76543210 76543210
> ||| ------- gen -----------||-----index-|
>
> which is what we wanted.
>
> As we saw from the C standard there is no good solution working under
> any circumstances. But the kernel uses such structs with the define
> __LITTLE_ENDIAN_BITFIELD, and therfore a solution to make the struct
> above working on big endian machines too would be:
>
> struct mpls_gen_key {
> #if defined (__LITTLE_ENDIAN_BITFIELD)
> unsigned int index:10;
> unsigned int gen:20;
> unsigned int type:2;
> #else
> unsigned int type:2;
> unsigned int gen:20;
> unsigned int index:10;
> #endif
> };
>
> What do you think?
>
> Kind regards,
> Georg Klug
>
>
>
> -------------------------------------------------------
> This sf.net email is sponsored by:ThinkGeek
> Welcome to geek heaven.
> http://thinkgeek.com/sf
> _______________________________________________
> mpls-linux-general mailing list
> mpl...@li...
> https://lists.sourceforge.net/lists/listinfo/mpls-linux-general
--
James R. Leu
|