I'm trying to build a simple custom application layer protocol, essentially carrying a timestamp, plus some other useful information, in order to perform few network measurements between different Linux systems.
The implementation, in my initial idea, should be as portable as possible between different platforms (x86, ARM, ...), as far as Linux systems are concerned.
In order to manage the header, I've created this structure:
struct myhdr {
__u8 reserved; // 1 byte
__u8 ctrl; // 1 byte
__u16 id; // 2 bytes
__u16 seq; // 2 bytes
__u16 len; // 2 bytes
struct timeval sendtime; // 8 or 16 bytes
};
After which some payload data may or may not (if len=0) be present. Since this data has to be sent over the network, I need, if I'm not wrong, the structure to be packed, without any alignment padding.
My doubt is actually whether this can be considered as already packed or not, mainly due to the presence of struct timeval
, to carry the timestamp.
Under 32 bit systems, struct timeval
should be 8 bytes. Under 64 bit systems, it should be 16 bytes (just tested this by printing sizeof(struct timeval)
).
Under 32 bit systems, is it safe to assume it to be already packed, due to the fact that 1+1+2+2+2 bytes = 8 bytes, which is the size of sendtime
? Or will be a padding added in any case in order to align every single field to the last one, which is the largest?
What happens then in 64 bit systems, where the last field is 16 bytes? I think that the structure won't be "packed by layout" anymore, in any case (is this correct?).
Is adding __attribute__((packed))
sufficient and always necessary to ensure that the structure is packed when the code is compiled for different platforms? Are there better solutions?