On Tue, 2004-05-04 at 15:41, address@hidden wrote:
On Tue, 2004-05-04 at 01:04, Timmy Brolin wrote:
Mandatory
alignment would render all those STRUCT_PACK macros unnecessary,
resulting in cleaner code, and significantly increased portability (ANSI
C conformant, no alignment problem, and no need to define architecture
specific struct packing macros)
Padding of the start of the struct does not guarantee the alignment of
subsequent elements in that struct, so the packing is still required.
Kieran
Oh but it does.
The fields in the IP and TCP headers are properly aligned relative to the start
of the headers by design. The problem is that the ethernet header is 14 bytes
which is not a factor of four, so the starting address of the subsequent IP and
TCP structs become unaligned.
A compiler normaly fix struct alignment problems by silently inserting padding
between the fields in the struct (this is of course not acceptable). In order
to keep the compiler from doing so, there are struct packing compiler
directives in the lwip code. Theese compiler directives tell the compiler to
pack the structs even if they are unaligned. Not all compilers and processors
support this, it is not ANSI C, and the implementation is highly compiler
specific.
By padding the ethernet header to 16 bytes, we ensure that the IP and TCP
structs are correctly aligned. And since there are no alignment problems, the
compiler will not add any padding. Thus, we don't need the struct packing
directives.
There are two issues here which you seem to be confusing:
1) Ensuring that the IP header is aligned on a 32bit boundary. The
standard way to do this is to reserve two bytes before the ethernet
header (if you happen to be using Ethernet) so that the following IP
header is 32 bit aligned. I think we agree on this: you certainly have
no argument from me that this is a good thing, and I thought the
Ethernet driver already supported this.
2) Ensuring that the structs do not have gaps between fields. This is
independent of anything to do with Ethernet having 14 byte headers, or
the alignment of the network headers. It is simply ensuring that all
the elements are sequential in memory with no gaps. Just making sure
the start of the struct is 32bit aligned will not guarantee this. On
64bit alpha architectures for example I've run into problems where a
non-packed struct would have padding inserted *in the middle* of the
struct, as the compiler could access it more efficiently that way. I
know the GCC pack directives are not ANSI C, but there is no other way
that I am aware of, other than not using structs at all, to ensure this.
That is why we use the packed struct directives. If you know of an
alternative that is more standards compliant, please let us know.
Hope that clarifies the reasons why we need both padding and packing!
Kieran