This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Contiguous memory space in type definitions

Hello everybody.

Once again, I'm sorry if I'm asking something too obvious.
I have defined some structures in C to access the different fields of an Ethernet frame in a more elegant way than using simple byte arrays. The structure is:

typedef struct {
        u8              DestMACAddr[6];
        u8              SrcMACAddr[6];
        u16             LengthType;
        union {
                struct {
                        u16             QTagCtlInfo;
                        u16             LengthType;
                        u8              Payload[1500];
                        u8              ALIGN[2];               // So that the data type is 32-bit aligned
                } TAGGED;

                u8              Payload[1500];
        } Content;
} EthernetFrameType;

, which works pretty much OK.

Now, to process the ARP frames in a similar way, I define the following type:

// ARP Protocol Payload Type
typedef struct {
        u16     HwType;
        u16     ProtType;
        u16     HwProtLengths;
        u16     Operation;
        u8      SrcMAC[6];
        u32     SrcIP;
        u8      DestMAC[6];
        u32     DestIP;
} ARPPayloadType;

Then I use a pointer of type ARPPayloadType to access the Payload field in the EthernetFrame:

EthernetFrameType frame;
ARPPayloadType *arp;

arp = (ARPPayloadType *)frame.Content.Payload;

if (arp->Operation == 0x0100) {
        //It's a request
} else if (arp->Operation == 0x0200) {
        //It's a response
}

I use these data types in the tx. and rx. buffers for the Ethernet controller.

My problem is that it is not working. For some reason, the compiler reserves 8 bytes for the MAC address fields in the ARP type definition, but assigns the others fields their expected sizes. I mean: I have checked the address where each field is stored, and all of them are where expected, except for the SrcMAC and DestMAC fields within the ARPPayloadType structure, which are both 8 bytes long (thus moving the SrcIP and DestIP fields two bytes forward their expected positions).

I thought that maybe this had something to do with word alignment,but the buffers are 32 bits aligned, and their size is adjusted so that two contiguous frames (such as those in an array) do not 'break' that alignment (that's the purpose of the "ALIGN" field).

I know that we are not suppossed to have such a precise control on the data storage, and that leaving or not "blanks" in the middle of two suppossedly contigous data containers is a decission of the compiler, but I don't understand why it happens only in the ARP part, and only in that fields, and not in the Ethernet header part, which also has two MAC address fields (the ones which are neither 16-bit nor 32-bit aligned).

So, do you have any clues on why this is so? Any workarounds? Should I read the data using a byte array and stop messing things up?

Thank you very much for you answers.

Parents
  • Actually, it's probably not more elegant at all.

    You will end up constantly having to fight the compiler's desire to align things.
    (you may also be fighting the processor's requirement for things to be aligned)

    You could pick the bytes out of the arrya into a separate structure "buffer" - but it probably isn't worth trying to "map" a structure onto the raw bytes...

    To you, 2p.

Reply
  • Actually, it's probably not more elegant at all.

    You will end up constantly having to fight the compiler's desire to align things.
    (you may also be fighting the processor's requirement for things to be aligned)

    You could pick the bytes out of the arrya into a separate structure "buffer" - but it probably isn't worth trying to "map" a structure onto the raw bytes...

    To you, 2p.

Children