lwip-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [lwip-users] Struct packing/alignment problems


From: Timmy Brolin
Subject: Re: [lwip-users] Struct packing/alignment problems
Date: Mon, 26 Apr 2004 12:34:00 +0200
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.4) Gecko/20030624 Netscape/7.1 (ax)

That's alot of work you have done there.
A decent solution to this alignment problem is really needed, because as it is now, lwip is incompatible with most 32bit embedded CPUs.(!!) (Such as ARM, TI DSPs, ...) I have been thinking some more.. Four u8_t is actually not very optimal, two u16_t might be a better solution. Two u16_t fields equals about the same performance as a unaligned u32_t even on systems that do support unaligned memory accesses, so replacing all 32 bit fields with two u16_t should work fine for all architectures.
(A 32bit unaligned memory read usually results in two memory read cycles)

I have also been considering a second approach where I add a 16bit pad to the very beginning of the ethernet header. No data must be rearranged, the packet is simply written to offset 2 into the pbuf. This way all 32bit fields become aligned except for the dipaddr in the ARP header. This field can be substituted with two u16_t, and everything is solved. This solution should actually increase performance slightly, even on 32bit systems that do support unaligned memory accesses. The only bad thing is that two bytes per packet are wasted.

When the alignment problem is solved, we can get rid of all thoose ugly PACK_STRUCT makros, because they are only needed for unaligned structs.

Timmy Brolin

Mountifield, Tony wrote:

I considered solving the problem by changing the ip_addr struct from:
struct ip_addr {
 u32_t addr;
}
To something like:
struct ip_addr {
 u8_t addr0;
 u8_t addr1;
 u8_t addr2;
 u8_t addr3;
}

But I found that this struct is used in tons of places. That's alot of code to rewrite..
Have anyone solved this problem without introducing padding?

Yes, I had to use a similar approach to what you suggested:

struct ip_addr {
 u8_t addrb[4];
}

I changed the name to ensure the compiler would catch all occurrences.

I then used macros to access the address. When copying, I used structure copy, i.e. instead of 
"p->addr = x->y.addr;" I did "*p = x->y;". I defined htonlb() and ntohlb() 
functions too.

A lot of the required changes are actually in LWIP_DEBUGF statements.

The next thing I found was that similar changes were needed for the seqno and 
ackno in the TCP header, which are also unaligned, and so need redefinition as 
u8_t arrays. It is then necessary to be careful about byte order. Instead of 
rewriting the header in the received buffer, I left the seqno and ackno in 
network byte order in the header, but transformed to native order when copying 
to local variables.

I have hesitated to submit my changes yet, because there are still a few 
kludges and also I haven't yet ensured portability back to CPUs and compilers 
that don't need all this trickery. Also because I've been doing it as paid work.

Cheers,
Tony


***********************************************************************************
This email, its content and any attachments is PRIVATE AND
CONFIDENTIAL to TANDBERG Television. If received in error please
notify the sender and destroy the original message and attachments.

www.tandbergtv.com
***********************************************************************************



_______________________________________________
lwip-users mailing list
address@hidden
http://mail.gnu.org/mailman/listinfo/lwip-users








reply via email to

[Prev in Thread] Current Thread [Next in Thread]