RE: [mpls-linux-general] Endianess and bitfields
Status: Beta
Brought to you by:
jleu
|
From: Georg K. <gk...@gi...> - 2002-10-30 12:30:36
|
Hi Jim,
> 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.
I would usually agree, if the code would only interpret the bitfields
when they were set that way. But have a look at the following lines in
the function mpls_print_key:
--------------------------- snip ---------------------
void mpls_print_key(u32 key) {
struct mpls_key mlk;
mlk.u.mark = key;
switch(mlk.u.gen.type) {
case MPLS_LABEL_GEN:
printk("Key GEN %d %d\n",mlk.u.gen.gen,mlk.u.gen.index);
break;
--------------------------- snip ---------------------
Those construction, where a union is assigned via u32 and then interpreted
as a bitfield, need the bitfield ordered correctly. (Especiall if a key is
assigned through the function mpls_get_out_key() and then printed via
mpls_print_key() it will lead to wrong output).
So I would recommend at least to use the define __LITTLE_ENDIAN_BITFIELD.
> 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.
They use a BITFIELD_ASCENDING macro depending on the
LITTLE/BIG_ENDIAN_BYTE_ORDER,
which is not portable in general, but works for gcc used with Linux.
As I pointed out before, using bitfields is not portable in general,
since the ordering is compiler and machine dependent and not defined in the
C standard. Please see the following thread in the ppc-dev List as a reference.
http://www.geocrawler.com/mail/thread.php3?subject=Help+with+cross-endian+bitfie
lds%3F&list=3
Do you agree?
Kind regards,
Georg klug
>
> 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
>
>
> -------------------------------------------------------
> 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
>
|