Get in touch:
01524 851 877
07718 896 553

Structure Packing in GCC

Posted on Mar 26 2008

I have recently been doing a lot of coding using the NEPL NEMO Implementation as a part of a project I am working on. This has proved to be very interesting work and has brought about lots of interesting problems.

One of the most recent problems I faced involved a packet I was sending over the network using a header I had constructed using a struct as follows.

struct Nino
{
uint8_t type;
uint8_t length;
uint8_t prefix_len;
uint8_t res_l_4;
uint32_t nino_lifetime;
uint32_t reserved2;
uint8_t nino_depth;
uint8_t reserved3;
uint16_t nino_seq;
struct in6_addr _prefix_in6_addr;
};

This was the exact packet header format that I required but when I received a packet and checked it using a version of Wireshark I had modified to recognise the header format, I was getting what seemed like an erroneous 2 Bytes of data (set to 0’s) at the beginning of the in6_addr. This puzzled me for a while until I started to think about how GCC would lay out the fields in the struct. Of course GCC tries to optimise the struct for passing across the hardware and pads it if it feels it is necessary.

For my purposes this ruins the whole layout of the packet header for processing so I had a look around and found that GCC has an attribute named __packed__ that will force it not to pad the struct out. Or in the terms of the GCC Manual :

  • “a variable or structure field should have the smallest possible alignment–one byte for a variable, and one bit for a field, unless you specify a larger value with the aligned attribute.”

This was exactly what I wanted. So by changing the struct definition from that above, to :

struct Nino
{
uint8_t type;
uint8_t length;
uint8_t prefix_len;
uint8_t res_l_4;
uint32_t nino_lifetime;
uint32_t reserved2;
uint8_t nino_depth;
uint8_t reserved3;
uint16_t nino_seq;
struct in6_addr _prefix_in6_addr;
}__attribute__((__packed__));

My code behaved exactly as I required. Problem solved. This is a handy little function of GCC especially when dealing with network packets to make sure you know exactly how the compiler is behaving and hence avoiding any unwanted surprised.

A slightly more in depth look at the packed attribute can be found here.