TCP header and endianess - TCP-IP
This is a discussion on TCP header and endianess - TCP-IP ; While looking at the Linux tcp.h header file, I see the following:
struct tcphdr
{
u_int16_t source;
u_int16_t dest;
u_int32_t seq;
u_int32_t ack_seq;
# if __BYTE_ORDER == __LITTLE_ENDIAN
u_int16_t res1:4;
u_int16_t doff:4;
u_int16_t fin:1;
u_int16_t syn:1;
u_int16_t rst:1;
u_int16_t psh:1;
...
-
TCP header and endianess
While looking at the Linux tcp.h header file, I see the following:
struct tcphdr
{
u_int16_t source;
u_int16_t dest;
u_int32_t seq;
u_int32_t ack_seq;
# if __BYTE_ORDER == __LITTLE_ENDIAN
u_int16_t res1:4;
u_int16_t doff:4;
u_int16_t fin:1;
u_int16_t syn:1;
u_int16_t rst:1;
u_int16_t psh:1;
u_int16_t ack:1;
u_int16_t urg:1;
u_int16_t res2:2;
# elif __BYTE_ORDER == __BIG_ENDIAN
u_int16_t doff:4;
u_int16_t res1:4;
u_int16_t res2:2;
u_int16_t urg:1;
u_int16_t ack:1;
u_int16_t psh:1;
u_int16_t rst:1;
u_int16_t syn:1;
u_int16_t fin:1;
u_int16_t window;
u_int16_t check;
u_int16_t urg_ptr;
};
I am a bit confused about the bit-ordering. I thought big-endianess and
little-endianess apply only to "bytes" within either a 16 bit integer (hence
ntohs and htons) or 32-bit integers (hence nthol and htonl). So why are
they re-ordering the "bits" within a byte? i.e. why are the flag bits in
reverse order for little-endianess?
-
Re: TCP header and endianess
On May 3, 11:26*pm, "barcaroller" wrote:
> While looking at the Linux tcp.h header file, I see the following:
>
> struct tcphdr
> {
> * * u_int16_t source;
> * * u_int16_t dest;
> * * u_int32_t seq;
> * * u_int32_t ack_seq;
> # *if __BYTE_ORDER == __LITTLE_ENDIAN
> * * u_int16_t res1:4;
> * * u_int16_t doff:4;
> * * u_int16_t fin:1;
> * * u_int16_t syn:1;
> * * u_int16_t rst:1;
> * * u_int16_t psh:1;
> * * u_int16_t ack:1;
> * * u_int16_t urg:1;
> * * u_int16_t res2:2;
> # *elif __BYTE_ORDER == __BIG_ENDIAN
> * * u_int16_t doff:4;
> * * u_int16_t res1:4;
> * * u_int16_t res2:2;
> * * u_int16_t urg:1;
> * * u_int16_t ack:1;
> * * u_int16_t psh:1;
> * * u_int16_t rst:1;
> * * u_int16_t syn:1;
> * * u_int16_t fin:1;
>
> * * u_int16_t window;
> * * u_int16_t check;
> * * u_int16_t urg_ptr;
>
> };
>
> I am a bit confused about the bit-ordering. *I thought big-endianess and
> little-endianess apply only to "bytes" within either a 16 bit integer (hence
> ntohs and htons) or 32-bit integers (hence nthol and htonl). *So why are
> they re-ordering the "bits" within a byte? i.e. why are the flag bits in
> reverse order for little-endianess?
This is because the bits defined in structure are endianess relative.
The C programming language points this when introduce bits in struct.
You can check it.
Regards,
Matthew
-
Re: TCP header and endianess
In article
,
Matthew Xu wrote:
> On May 3, 11:26*pm, "barcaroller" wrote:
> > While looking at the Linux tcp.h header file, I see the following:
> >
> > struct tcphdr
> > {
> > * * u_int16_t source;
> > * * u_int16_t dest;
> > * * u_int32_t seq;
> > * * u_int32_t ack_seq;
> > # *if __BYTE_ORDER == __LITTLE_ENDIAN
> > * * u_int16_t res1:4;
> > * * u_int16_t doff:4;
> > * * u_int16_t fin:1;
> > * * u_int16_t syn:1;
> > * * u_int16_t rst:1;
> > * * u_int16_t psh:1;
> > * * u_int16_t ack:1;
> > * * u_int16_t urg:1;
> > * * u_int16_t res2:2;
> > # *elif __BYTE_ORDER == __BIG_ENDIAN
> > * * u_int16_t doff:4;
> > * * u_int16_t res1:4;
> > * * u_int16_t res2:2;
> > * * u_int16_t urg:1;
> > * * u_int16_t ack:1;
> > * * u_int16_t psh:1;
> > * * u_int16_t rst:1;
> > * * u_int16_t syn:1;
> > * * u_int16_t fin:1;
> >
> > * * u_int16_t window;
> > * * u_int16_t check;
> > * * u_int16_t urg_ptr;
> >
> > };
> >
> > I am a bit confused about the bit-ordering. *I thought big-endianess and
> > little-endianess apply only to "bytes" within either a 16 bit integer (hence
> > ntohs and htons) or 32-bit integers (hence nthol and htonl). *So why are
> > they re-ordering the "bits" within a byte? i.e. why are the flag bits in
> > reverse order for little-endianess?
>
> This is because the bits defined in structure are endianess relative.
> The C programming language points this when introduce bits in struct.
> You can check it.
Actually, I think the order of bit fields is left
implementation-dependent by the C language. It just so happens that
most implementations lay them out consistently with the endianness.
--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE don't copy me on replies, I'll read them in the group ***
-
Re: TCP header and endianess
On May 4, 3:39*pm, Barry Margolin wrote:
> > > I am a bit confused about the bit-ordering. *I thought big-endianessand
> > > little-endianess apply only to "bytes" within either a 16 bit integer (hence
> > > ntohs and htons) or 32-bit integers (hence nthol and htonl). *So whyare
> > > they re-ordering the "bits" within a byte? i.e. why are the flag bits in
> > > reverse order for little-endianess?
> Actually, I think the order of bit fields is left
> implementation-dependent by the C language. *It just so happens that
> most implementations lay them out consistently with the endianness.
That's annoying. Since the most common setup these days is IP over
Ethernet, meaning big endian byte order and little endian bit order in
each byte, switching simultaneously both the bit and the byte order is
a perfect formula for creating confusion.
Good to know, though. Chalk it up to "tricks of the trade."
Bert
-
Re: TCP header and endianess
In article
,
Albert Manfredi wrote:
> On May 4, 3:39*pm, Barry Margolin wrote:
>
> > > > I am a bit confused about the bit-ordering. *I thought big-endianess
> > > > and
> > > > little-endianess apply only to "bytes" within either a 16 bit integer
> > > > (hence
> > > > ntohs and htons) or 32-bit integers (hence nthol and htonl). *So why
> > > > are
> > > > they re-ordering the "bits" within a byte? i.e. why are the flag bits
> > > > in
> > > > reverse order for little-endianess?
>
> > Actually, I think the order of bit fields is left
> > implementation-dependent by the C language. *It just so happens that
> > most implementations lay them out consistently with the endianness.
>
> That's annoying. Since the most common setup these days is IP over
> Ethernet, meaning big endian byte order and little endian bit order in
> each byte, switching simultaneously both the bit and the byte order is
> a perfect formula for creating confusion.
Yeah. The C designers didn't really intend bit fields to be used for
external data.
The way to write bit-twiddling code portably is to use shifting and
masking, rather than bit fields.
--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE don't copy me on replies, I'll read them in the group ***
-
Re: TCP header and endianess
On Sun, 04 May 2008 20:29:04 -0400, Barry Margolin wrote:
> In article
> ,
> Albert Manfredi wrote:
>
>> On May 4, 3:39*pm, Barry Margolin wrote:
>>
>> > > > I am a bit confused about the bit-ordering. *I thought big-endianess
>> > > > and
>> > > > little-endianess apply only to "bytes" within either a 16 bit integer
>> > > > (hence
>> > > > ntohs and htons) or 32-bit integers (hence nthol and htonl). *So why
>> > > > are
>> > > > they re-ordering the "bits" within a byte? i.e. why are the flag bits
>> > > > in
>> > > > reverse order for little-endianess?
>>
>> > Actually, I think the order of bit fields is left
>> > implementation-dependent by the C language. *It just so happens that
>> > most implementations lay them out consistently with the endianness.
>>
>> That's annoying. Since the most common setup these days is IP over
>> Ethernet, meaning big endian byte order and little endian bit order in
>> each byte, switching simultaneously both the bit and the byte order is
>> a perfect formula for creating confusion.
>
> Yeah. The C designers didn't really intend bit fields to be used for
> external data.
>
> The way to write bit-twiddling code portably is to use shifting and
> masking, rather than bit fields.
Yes. And in my experience, you typically do not gain a lot of
readability by mapping onto structs and bitfields. When I have
rewritten code to use a few well-chosen encoding/decoding functions
instead of structs and bit fields, it has become *more* readable.
Also, for the struct tcphdr in the original example, note that if you
cast some char * or void * buffer to a struct tcphdr *, you better
make sure it is word-aligned. Otherwise, depending on your CPU
architecture, you may get a bus error, or suffer drastic performance
reduction.
/Jorgen
--
// Jorgen Grahn
\X/ snipabacken.se> R'lyeh wgah'nagl fhtagn!