Re: [mpls-linux-general] Endianess and bitfields
Status: Beta
Brought to you by:
jleu
|
From: James R. L. <jl...@mi...> - 2002-10-30 14:59:59
|
If the code was relying on the location of the bits within the unsigned
int, then I would have to take into account endianess. Since the code only
uses the bit fields to form a unique key and does not try to access the bit
values once they have been converted to a key, there is no need to be concerned
about byte-ordering.
Try this simple program on a x86 and PPC and you will see it just doesn't
matter.
#include <stdio.h>
#include <string.h>
struct bitfield {
unsigned int foo:10;
unsigned int bar:20;
unsigned int shemp:2;
};
struct holder {
union {
struct bitfield bits;
unsigned int mark;
} u;
};
int main(int argc, char **argv) {
unsigned int intermediate;
struct holder test;
memset(&test,0,sizeof(test));
test.u.bits.foo = 1022;
test.u.bits.bar = 33;
test.u.bits.shemp = 2;
intermediate = test.u.mark;
memset(&test,0,sizeof(test));
test.u.mark = intermediate;
fprintf(stdout, "foo: %d bar: %d shemp: %d\n", test.u.bits.foo,
test.u.bits.bar, test.u.bits.shemp);
return 0;
}
On Wed, Oct 30, 2002 at 01:33:45PM +0100, Georg Klug wrote:
> 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
> >
>
--
James R. Leu
|