Structure Packing
Prev | Chapter 3. Software | Next

## Structure Packing

Programs in this toolkit make extensive use of packed data structures to simplify source code and guarantee reliability; however, this creates portability issues because different compilers implement structure packing in different ways. Three common structure packing mechanisms are:

_packed

  The __packed keyword is not part of any C or C++ standard but it is recognized by some compilers, such as the ARM C/C++ and OpenBSD C compiler. This keyword only affects the data structure that it prefaces and it is an ideal way to selectively pack structures. It can be easily defined and undefined using a preprocessor macro. Atheros has elected to insert this keyword wherever it might be appropriate. The ARM C compilers accept this keyword.

  Example 3.5. Packing Structures with keyword “__packed”

      typedef struct __packed header_eth
      {
      	uint8_t source [ETHER_ADDR_LEN];
      	uint8_t target [ETHER_ADDR_LEN];
      	uint16_t protocol;
      }
      header_eth;

__attribute__ ((packed))

  Attributes are not part of any C or C++ standard but they are recognized by the gcc and Sun Microsystems C compiler. Attributes only affect structures and functions that reference them in their declaration. This is convenient because we can use a preprocessor macro to define the keyword `__packed`, mentioned above, to be `__attribute__ ((packed))`. Atheros includes this definition in `tools/types.h` and OpenBSD does this in their system header files.

  Example 3.6. Packing Structures with Attribute “packed”

      typedef struct __attribute__ ((packed)) header_eth
      {
      	uint8_t source [ETHER_ADDR_LEN];
      	uint8_t target [ETHER_ADDR_LEN];
      	uint16_t protocol;
      }
      header_eth;

#pragrma pack

  Pragmas are part of most C and C++ language standards but some compilers do not recognize or implement the `pack` pragma. In addition, different compilers implement it in different ways. The `pack` pragma affects all data structures up the next `pack` pragma or end of compile unit. Most pragma implementations accept the push and pop option for pragma nesting. Some pragma pack implementations accept no arguments, most permit either one or two arguments while others allow three arguments. OpenBSD does not recognize this pragma and generates warnings in all cases. Aside from all that, the pack pragma is the most widely supported method for declaring packed structures.

  Example 3.7. Packing Structures with the Pragma “pack”

      #pragma pack (push, 1)
      struct header_eth
      {
      	uint8_t source [ETHER_ADDR_LEN];
      	uint8_t target [ETHER_ADDR_LEN];
      	uint16_t protocol;
      }
      header_eth;
      #pragma pack (pop)

The Atheros Way

  Toolkit programs declares packed structures using all three methods, as shown below.

  Example 3.8. Packing Structures the Atheros Way

      #ifndef __packed
      #ifdef __GNUC__
      #define __packed __attribute__ ((packed))
      #else
      #define __packed
      #endif
      #endif

      #ifndef __GNUC__
      #pragma pack (push, 1)
      #endif

      struct __packed header_eth
      {
      	uint8_t source [ETHER_ADDR_LEN];
      	uint8_t target [ETHER_ADDR_LEN];
      	uint16_t protocol;
      }
      header_eth;

      #ifndef __GNUC__
      #pragma pack (pop)
      #endif

Prev | Up | Next
LibPcap, WinPcap and BPF | Home | Endian-ness