netpoll endian fixes
PATCH 1/1 netpoll endian fixes
The big-endians took their revenge in netpoll.c: on i386, the ip header length / version nibbles need to be the other way round; and the htonl leaves only zeros in tot_len...
All the best,
Duncan.
net/core/netpoll.c renamed from net/core/netpoll.c.orig +6 -1
@@ -22,6 +22,7 @@#include <net/tcp.h> #include <net/udp.h> #include <asm/unaligned.h> +#include <asm/byteorder.h> /* * We maintain a small pool of fully-sized skbs, to make sure the
@@ -242,9 +243,13 @@ iph = (struct iphdr *)skb_push (skb,sizeof (*iph));/* iph->version = 4; iph->ihl = 5; */ +#if defined(__LITTLE_ENDIAN_BITFIELD) +put_unaligned (0x45 , (unsigned char *)iph); +#else put_unaligned (0x54 , (unsigned char *)iph); +#endif iph->tos =0 ; -put_unaligned (htonl (ip_len), &(iph->tot_len)); +put_unaligned (htons (ip_len), &(iph->tot_len)); iph->id =0 ; iph->frag_off =0 ; iph->ttl =64 ;
Quoted 3 lines · Duncan Sands
The big-endians took their revenge in
netpoll.c: on i386, the ip header length / version nibbles need to be the other way round; and the htonl leaves only zeros intot_len...
I'm completely baffled as to how length / version nibbles could be swapped. Endianness here should be a matter of _bytes_.
The htons seems reasonable.
Signature · 1 line
Mathematics is the supreme nostalgia of our time.
Quoted 7 lines · Matt Mackall
Quoted 3 lines · Duncan Sands
The big-endians took their revenge in
netpoll.c: on i386, the ip header length / version nibbles need to be the other way round; and the htonl leaves only zeros intot_len...I'm completely baffled as to how length / version nibbles could be swapped. Endianness here should be a matter of _bytes_.
I also don't understand it. The definition of struct iphdr contains:
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 ihl:4,
version:4;
#elif defined (__BIG_ENDIAN_BITFIELD)
__u8 version:4,
ihl:4;What does it mean?
All the best,
Duncan.
Quoted 20 lines · Duncan Sands
The big-endians took their revenge in
netpoll.c: on i386, the ip header length / version nibbles need to be the other way round; and the htonl leaves only zeros intot_len...All the best,
Duncan.
net/core/netpoll.c renamed from net/core/netpoll.c.orig +1
-0@@ -22,6 +22,7 @@#include <net/tcp.h> #include <net/udp.h> #include <asm/unaligned.h> +#include <asm/byteorder.h> /* * We maintain a small pool of fully-sized skbs, to make sure the
net/core/netpoll.c line 250
Quoted 8 lines
net/core/netpoll.c renamed from net/core/netpoll.c.orig +4
-0@@ -242,9 +243,13 @@ iph = (struct iphdr *)skb_push (skb,sizeof (*iph));/* iph->version = 4; iph->ihl = 5; */ +#if defined(__LITTLE_ENDIAN_BITFIELD) +put_unaligned (0x45 , (unsigned char *)iph); +#else put_unaligned (0x54 , (unsigned char *)iph); +#endif
Probably what's happened is this:
The original person who sent me the alignment fixes sent a similar bizarre endian #ifdef thing. He didn't send it as a proper patch though, so I redid it and copied the not-so-obviously incorrect clause.
It looks like it ought to be 0x45 everywhere, meaning it's currently broken everywhere. But no one's complained. Unfortunately at the present moment I've got one machine short of a test rig unpacked, so I'm loathe to push another fix until I get some other test reports. Anyone else run into trouble with netpoll/netconsole in recent -mm or -bk?
Signature · 1 line
Mathematics is the supreme nostalgia of our time.
Quoted 4 lines
It looks like it ought to be
0x45everywhere, meaning it's currently broken everywhere. But no one's complained. Unfortunately at the present moment I've got one machine short of a test rig unpacked, so I'm loathe to push another fix until I get some other test reports.
Hi Matt, I agree that it should be 0x45 everywhere. After thinking a bit I concluded that the
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 ihl:4,
version:4;
#elif defined (__BIG_ENDIAN_BITFIELD)
__u8 version:4,
ihl:4;in the definition of struct iphdr is to make sure that compiler uses the first four bits of the byte to refer to version, rather than the last four; and this only matters when you are accessing the nibbles via the ihl or version structure fields. Thus it makes sure that if you write 0x45 to the byte, then version will return 4 and ihl will return 5. Presumably the C standard specifies how bitfield expressions should be laid out in the byte, and ihl:4, version:4; gives opposite results on little-endian and big-endian machines...
Ciao,
Duncan.
Quoted 24 lines · Duncan Sands
Quoted 4 lines
It looks like it ought to be
0x45everywhere, meaning it's currently broken everywhere. But no one's complained. Unfortunately at the present moment I've got one machine short of a test rig unpacked, so I'm loathe to push another fix until I get some other test reports.Hi Matt, I agree that it should be
0x45everywhere. After thinking a bit I concluded that the#if defined(__LITTLE_ENDIAN_BITFIELD) __u8 ihl:4, version:4; #elif defined (__BIG_ENDIAN_BITFIELD) __u8 version:4, ihl:4;in the definition of struct iphdr is to make sure that compiler uses the first four bits of the byte to refer to version, rather than the last four; and this only matters when you are accessing the nibbles via the ihl or version structure fields. Thus it makes sure that if you write
0x45to the byte, then version will return 4 and ihl will return 5. Presumably the C standard specifies how bitfield expressions should be laid out in the byte, and ihl:4, version:4; gives opposite results on little-endian and big-endian machines...
Quoted 3 lines
Ciao,
Duncan.
Ok, could you send an updated patch with a Signed-off-by, please?
Signature · 1 line
Mathematics is the supreme nostalgia of our time.
Quoted 1 line
Ok, could you send an updated patch with a Signed-off-by, please?
Here you are:
Correct wrong ip header in netpoll_send_udp.
net/core/netpoll.c renamed from net/core/netpoll.c.orig +2 -2
@@ -242,9 +242,9 @@ iph = (struct iphdr *)skb_push (skb,sizeof (*iph));/* iph->version = 4; iph->ihl = 5; */ -put_unaligned (0x54 , (unsigned char *)iph); +put_unaligned (0x45 , (unsigned char *)iph); iph->tos =0 ; -put_unaligned (htonl (ip_len), &(iph->tot_len)); +put_unaligned (htons (ip_len), &(iph->tot_len)); iph->id =0 ; iph->frag_off =0 ; iph->ttl =64 ;