sfc: fix unaligned access in loopback selftests
Subsystems (3)
cover sfc: fix unaligned access in loopback selftests
From: Edward Cree <[email protected]>
Arnd reported that the sfc drivers each define a packed loopback_payload
structure with an ethernet header followed by an IP header, whereas the kernel definition of iphdr specifies that this is 4-byte aligned, causing a W=1 warning.
Fix this in each case by adding two bytes of leading padding to the
struct, taking care that these are not sent on the wire.
Tested on EF10; build-tested on Siena and Falcon.
Edward Cree (3):
sfc: use padding to fix alignment in loopback test
sfc: siena: use padding to fix alignment in loopback test
sfc: falcon: use padding to fix alignment in loopback test
drivers/net/ethernet/sfc/falcon/selftest.c | 45 +++++++++++++--------- drivers/net/ethernet/sfc/selftest.c | 45 +++++++++++++--------- drivers/net/ethernet/sfc/siena/selftest.c | 45 +++++++++++++--------- 3 files changed, 81 insertions(+), 54 deletions(-)
PATCH 1/3 sfc: use padding to fix alignment in loopback test
From: Edward Cree <[email protected]>
Add two bytes of padding to the start of struct efx_loopback_payload,
which are not sent on the wire. This ensures the 'ip' member is
4-byte aligned, preventing the following W=1 warning:net/ethernet/sfc/selftest.c:46:15: error: field ip within 'struct efx_loopback_payload' is less aligned than 'struct iphdr' and is usually due to 'struct efx_loopback_payload' being packed, which can lead to unaligned accesses [-Werror,-Wunaligned-access]
struct iphdr ip;
--- drivers/net/ethernet/sfc/selftest.c | 45 +++++++++++++++++------------ 1 file changed, 27 insertions(+), 18 deletions(-)
drivers/net/ethernet/sfc/selftest.c +27 -18
@@ -42,12 +42,16 @@* Falcon only performs RSS on TCP/UDP packets. */ struct efx_loopback_payload { +char pad[2 ];/* Ensures ip is 4-byte aligned */ struct ethhdr header;struct iphdr ip;struct udphdr udp;__be16 iteration;char msg[64 ]; } __packed; +#define EFX_LOOPBACK_PAYLOAD_LEN (sizeof(struct efx_loopback_payload) - \ + offsetof(struct efx_loopback_payload, \ + header))/* Loopback test source MAC address */ static const u8 payload_source[ETH_ALEN ]__aligned(2) = {
@@ -282,7 +286,7 @@ void efx_loopback_rx_packet(struct efx_nic *efx, const char *buf_ptr, int pkt_len) {struct efx_loopback_state *state = efx->loopback_selftest; -struct efx_loopback_payload *received; +struct efx_loopback_payload received;struct efx_loopback_payload *payload;BUG_ON (!buf_ptr);
@@ -293,13 +297,14 @@ void efx_loopback_rx_packet(struct efx_nic *efx, payload = &state->payload; - received = (struct efx_loopback_payload *) buf_ptr; - received->ip.saddr = payload->ip.saddr; +memcpy (&received.header, buf_ptr, +min_t (int, pkt_len,EFX_LOOPBACK_PAYLOAD_LEN )); + received.ip.saddr = payload->ip.saddr;if (state->offload_csum) - received->ip.check = payload->ip.check; + received.ip.check = payload->ip.check;/* Check that header exists */ -if (pkt_len <sizeof (received->header)) { +if (pkt_len <sizeof (received.header)) {netif_err (efx, drv, efx->net_dev,"saw runt RX packet (length %d) in %s loopback " "test\n" , pkt_len,LOOPBACK_MODE (efx));
@@ -307,7 +312,7 @@ void efx_loopback_rx_packet(struct efx_nic *efx, }/* Check that the ethernet header exists */ -if (memcmp (&received->header, &payload->header,ETH_HLEN ) !=0 ) { +if (memcmp (&received.header, &payload->header,ETH_HLEN ) !=0 ) {netif_err (efx, drv, efx->net_dev,"saw non-loopback RX packet in %s loopback test\n" ,LOOPBACK_MODE (efx));
@@ -315,16 +320,16 @@ void efx_loopback_rx_packet(struct efx_nic *efx, }/* Check packet length */ -if (pkt_len !=sizeof (*payload)) { +if (pkt_len !=EFX_LOOPBACK_PAYLOAD_LEN ) {netif_err (efx, drv, efx->net_dev,"saw incorrect RX packet length %d (wanted %d) in " -"%s loopback test\n" , pkt_len, (int )sizeof (*payload), -LOOPBACK_MODE (efx)); +"%s loopback test\n" , pkt_len, + (int )EFX_LOOPBACK_PAYLOAD_LEN ,LOOPBACK_MODE (efx)); goto err; }/* Check that IP header matches */ -if (memcmp (&received->ip, &payload->ip,sizeof (payload->ip)) !=0 ) { +if (memcmp (&received.ip, &payload->ip,sizeof (payload->ip)) !=0 ) {netif_err (efx, drv, efx->net_dev,"saw corrupted IP header in %s loopback test\n" ,LOOPBACK_MODE (efx));
@@ -332,7 +337,7 @@ void efx_loopback_rx_packet(struct efx_nic *efx, }/* Check that msg and padding matches */ -if (memcmp (&received->msg, &payload->msg,sizeof (received->msg)) !=0 ) { +if (memcmp (&received.msg, &payload->msg,sizeof (received.msg)) !=0 ) {netif_err (efx, drv, efx->net_dev,"saw corrupted RX packet in %s loopback test\n" ,LOOPBACK_MODE (efx));
@@ -340,10 +345,10 @@ void efx_loopback_rx_packet(struct efx_nic *efx, }/* Check that iteration matches */ -if (received->iteration != payload->iteration) { +if (received.iteration != payload->iteration) {netif_err (efx, drv, efx->net_dev,"saw RX packet from iteration %d (wanted %d) in " -"%s loopback test\n" ,ntohs (received->iteration), +"%s loopback test\n" ,ntohs (received.iteration),ntohs (payload->iteration),LOOPBACK_MODE (efx)); goto err; }
@@ -363,7 +368,8 @@ void efx_loopback_rx_packet(struct efx_nic *efx, buf_ptr, pkt_len, 0);netif_err (efx, drv, efx->net_dev,"expected packet:\n" );print_hex_dump (KERN_ERR ,"" ,DUMP_PREFIX_OFFSET ,0x10 ,1 , - &state->payload, sizeof(state->payload), 0); + &state->payload.header,EFX_LOOPBACK_PAYLOAD_LEN , + 0); }#endif atomic_inc (&state->rx_bad);
@@ -385,14 +391,15 @@ static void efx_iterate_state(struct efx_nic *efx) payload->ip.daddr =htonl (INADDR_LOOPBACK ); payload->ip.ihl =5 ; payload->ip.check = (__force __sum16 )htons (0xdead ); - payload->ip.tot_len =htons (sizeof (*payload) -sizeof (struct ethhdr )); + payload->ip.tot_len =htons (sizeof (*payload) - + offsetof(struct efx_loopback_payload , ip)); payload->ip.version =IPVERSION ; payload->ip.protocol =IPPROTO_UDP ;/* Initialise udp header */ payload->udp.source =0 ; - payload->udp.len =htons (sizeof (*payload) -sizeof (struct ethhdr ) - -sizeof (struct iphdr )); + payload->udp.len =htons (sizeof (*payload) - + offsetof(struct efx_loopback_payload , udp)); payload->udp.check =0 ;/* checksum ignored */ /* Fill out payload */
@@ -418,7 +425,7 @@ static int efx_begin_loopback(struct efx_tx_queue *tx_queue)for (i =0 ; i < state->packet_count; i++) {/* Allocate an skb, holding an extra reference for * transmit completion counting */ - skb =alloc_skb (sizeof (state->payload),GFP_KERNEL ); + skb =alloc_skb (EFX_LOOPBACK_PAYLOAD_LEN ,GFP_KERNEL );if (!skb)return -ENOMEM ; state->skbs[i] = skb;
@@ -429,6 +436,8 @@ static int efx_begin_loopback(struct efx_tx_queue *tx_queue) payload =skb_put (skb,sizeof (state->payload));memcpy (payload, &state->payload,sizeof (state->payload)); payload->ip.saddr =htonl (INADDR_LOOPBACK | (i <<2 )); +/* Strip off the leading padding */ +skb_pull (skb, offsetof(struct efx_loopback_payload , header));/* Ensure everything we've written is visible to the * interrupt handler. */
Re: [PATCH net-next 1/3] sfc: use padding to fix alignment in loopback test
Quoted 9 lines · On Thu, Jun 22, 2023, at 12:18, [email protected] wrote:
drivers/net/ethernet/sfc/selftest.c | 45 +++++++++++++++++------------ 1 file changed, 27 insertions(+), 18 deletions(-)drivers/net/ethernet/sfc/selftest.c +0
-0
drivers/net/ethernet/sfc/selftest.c line 51
Quoted 10 lines
drivers/net/ethernet/sfc/selftest.c +1
-0@@ -42,12 +42,16 @@* Falcon only performs RSS on TCP/UDP packets. */ struct efx_loopback_payload { +char pad[2 ];/* Ensures ip is 4-byte aligned */ struct ethhdr header;struct iphdr ip;struct udphdr udp;__be16 iteration;char msg[64 ]; } __packed;
There should probably be an extra __aligned(4) after the __packed, so that the compiler knows the start of the structure is aligned, otherwise (depending on the architecture and compiler), any access to a member can still turn into multiple single-byte accesses.
I would also expect to still see a warning without that extra attribute. Aside from this, the patch looks good to me.
Arnd
Edward Cree
maintainerRe: [PATCH net-next 1/3] sfc: use padding to fix alignment in loopback test
Quoted 17 lines · Arnd Bergmann
Quoted 16 lines · On Thu, Jun 22, 2023, at 12:18, [email protected] wrote:
drivers/net/ethernet/sfc/selftest.c | 45 +++++++++++++++++------------ 1 file changed, 27 insertions(+), 18 deletions(-)drivers/net/ethernet/sfc/selftest.c +1
-0@@ -42,12 +42,16 @@* Falcon only performs RSS on TCP/UDP packets. */ struct efx_loopback_payload { +char pad[2 ];/* Ensures ip is 4-byte aligned */ struct ethhdr header;struct iphdr ip;struct udphdr udp;
Quoted 8 lines
drivers/net/ethernet/sfc/selftest.c line 51
Quoted 3 lines
drivers/net/ethernet/sfc/selftest.c +0
-0__be16 iteration;char msg[64 ]; } __packed;There should probably be an extra
__aligned(4)after the__packed, so that the compiler knows the start of the structure is aligned, otherwise (depending on the architecture and compiler), any access to a member can still turn into multiple single-byte accesses.
Ok, will add that in v2.
Quoted 2 lines
I would also expect to still see a warning without that extra attribute. Aside from this, the patch looks good to me.
My compiler (gcc 8.3.1) doesn't reproduce the original warning, so
I'm flying slightly blind here :( If you could build-test this on your setup with/without the __aligned(4), I'd be very grateful.
-ed
Re: [PATCH net-next 1/3] sfc: use padding to fix alignment in loopback test
Quoted 8 lines · Edward Cree
Quoted 6 lines · Arnd Bergmann
On Thu, Jun 22, 2023, at 12:18, [email protected] wrote:
There should probably be an extra
__aligned(4)after the__packed, so that the compiler knows the start of the structure is aligned, otherwise (depending on the architecture and compiler), any access to a member can still turn into multiple single-byte accesses.
Quoted 7 lines
Ok, will add that in v2.
Quoted 2 lines
I would also expect to still see a warning without that extra attribute. Aside from this, the patch looks good to me.
My compiler (gcc 8.3.1) doesn't reproduce the original warning, so
I'm flying slightly blind here :( If you could build-test this on your setup with/without the__aligned(4), I'd be very grateful.
I can confirm that your patch addresses the warning for me with any version of clang I have installed, and that the __aligned(4) is not needed for the warning, though it is still a good idea for code generation.
Arnd
PATCH 2/3 sfc: siena: use padding to fix alignment in loopback test
In reply to [email protected]From: Edward Cree <[email protected]>
Add two bytes of padding to the start of struct efx_loopback_payload,
which are not sent on the wire. This ensures the 'ip' member is
4-byte aligned, preventing the following W=1 warning:net/ethernet/sfc/siena/selftest.c:46:15: error: field ip within 'struct efx_loopback_payload' is less aligned than 'struct iphdr' and is usually due to 'struct efx_loopback_payload' being packed, which can lead to unaligned accesses [-Werror,-Wunaligned-access]
struct iphdr ip;
--- drivers/net/ethernet/sfc/siena/selftest.c | 45 ++++++++++++++--------- 1 file changed, 27 insertions(+), 18 deletions(-)
drivers/net/ethernet/sfc/siena/selftest.c +27 -18
@@ -42,12 +42,16 @@* Falcon only performs RSS on TCP/UDP packets. */ struct efx_loopback_payload { +char pad[2 ];/* Ensures ip is 4-byte aligned */ struct ethhdr header;struct iphdr ip;struct udphdr udp;__be16 iteration;char msg[64 ]; } __packed; +#define EFX_LOOPBACK_PAYLOAD_LEN (sizeof(struct efx_loopback_payload) - \ + offsetof(struct efx_loopback_payload, \ + header))/* Loopback test source MAC address */ static const u8 payload_source[ETH_ALEN ]__aligned(2) = {
@@ -282,7 +286,7 @@ void efx_siena_loopback_rx_packet(struct efx_nic *efx, const char *buf_ptr, int pkt_len) {struct efx_loopback_state *state = efx->loopback_selftest; -struct efx_loopback_payload *received; +struct efx_loopback_payload received;struct efx_loopback_payload *payload;BUG_ON (!buf_ptr);
@@ -293,13 +297,14 @@ void efx_siena_loopback_rx_packet(struct efx_nic *efx, payload = &state->payload; - received = (struct efx_loopback_payload *) buf_ptr; - received->ip.saddr = payload->ip.saddr; +memcpy (&received.header, buf_ptr, +min_t (int, pkt_len,EFX_LOOPBACK_PAYLOAD_LEN )); + received.ip.saddr = payload->ip.saddr;if (state->offload_csum) - received->ip.check = payload->ip.check; + received.ip.check = payload->ip.check;/* Check that header exists */ -if (pkt_len <sizeof (received->header)) { +if (pkt_len <sizeof (received.header)) {netif_err (efx, drv, efx->net_dev,"saw runt RX packet (length %d) in %s loopback " "test\n" , pkt_len,LOOPBACK_MODE (efx));
@@ -307,7 +312,7 @@ void efx_siena_loopback_rx_packet(struct efx_nic *efx, }/* Check that the ethernet header exists */ -if (memcmp (&received->header, &payload->header,ETH_HLEN ) !=0 ) { +if (memcmp (&received.header, &payload->header,ETH_HLEN ) !=0 ) {netif_err (efx, drv, efx->net_dev,"saw non-loopback RX packet in %s loopback test\n" ,LOOPBACK_MODE (efx));
@@ -315,16 +320,16 @@ void efx_siena_loopback_rx_packet(struct efx_nic *efx, }/* Check packet length */ -if (pkt_len !=sizeof (*payload)) { +if (pkt_len !=EFX_LOOPBACK_PAYLOAD_LEN ) {netif_err (efx, drv, efx->net_dev,"saw incorrect RX packet length %d (wanted %d) in " -"%s loopback test\n" , pkt_len, (int )sizeof (*payload), -LOOPBACK_MODE (efx)); +"%s loopback test\n" , pkt_len, + (int )EFX_LOOPBACK_PAYLOAD_LEN ,LOOPBACK_MODE (efx)); goto err; }/* Check that IP header matches */ -if (memcmp (&received->ip, &payload->ip,sizeof (payload->ip)) !=0 ) { +if (memcmp (&received.ip, &payload->ip,sizeof (payload->ip)) !=0 ) {netif_err (efx, drv, efx->net_dev,"saw corrupted IP header in %s loopback test\n" ,LOOPBACK_MODE (efx));
@@ -332,7 +337,7 @@ void efx_siena_loopback_rx_packet(struct efx_nic *efx, }/* Check that msg and padding matches */ -if (memcmp (&received->msg, &payload->msg,sizeof (received->msg)) !=0 ) { +if (memcmp (&received.msg, &payload->msg,sizeof (received.msg)) !=0 ) {netif_err (efx, drv, efx->net_dev,"saw corrupted RX packet in %s loopback test\n" ,LOOPBACK_MODE (efx));
@@ -340,10 +345,10 @@ void efx_siena_loopback_rx_packet(struct efx_nic *efx, }/* Check that iteration matches */ -if (received->iteration != payload->iteration) { +if (received.iteration != payload->iteration) {netif_err (efx, drv, efx->net_dev,"saw RX packet from iteration %d (wanted %d) in " -"%s loopback test\n" ,ntohs (received->iteration), +"%s loopback test\n" ,ntohs (received.iteration),ntohs (payload->iteration),LOOPBACK_MODE (efx)); goto err; }
@@ -363,7 +368,8 @@ void efx_siena_loopback_rx_packet(struct efx_nic *efx, buf_ptr, pkt_len, 0);netif_err (efx, drv, efx->net_dev,"expected packet:\n" );print_hex_dump (KERN_ERR ,"" ,DUMP_PREFIX_OFFSET ,0x10 ,1 , - &state->payload, sizeof(state->payload), 0); + &state->payload.header,EFX_LOOPBACK_PAYLOAD_LEN , + 0); }#endif atomic_inc (&state->rx_bad);
@@ -385,14 +391,15 @@ static void efx_iterate_state(struct efx_nic *efx) payload->ip.daddr =htonl (INADDR_LOOPBACK ); payload->ip.ihl =5 ; payload->ip.check = (__force __sum16 )htons (0xdead ); - payload->ip.tot_len =htons (sizeof (*payload) -sizeof (struct ethhdr )); + payload->ip.tot_len =htons (sizeof (*payload) - + offsetof(struct efx_loopback_payload , ip)); payload->ip.version =IPVERSION ; payload->ip.protocol =IPPROTO_UDP ;/* Initialise udp header */ payload->udp.source =0 ; - payload->udp.len =htons (sizeof (*payload) -sizeof (struct ethhdr ) - -sizeof (struct iphdr )); + payload->udp.len =htons (sizeof (*payload) - + offsetof(struct efx_loopback_payload , udp)); payload->udp.check =0 ;/* checksum ignored */ /* Fill out payload */
@@ -418,7 +425,7 @@ static int efx_begin_loopback(struct efx_tx_queue *tx_queue)for (i =0 ; i < state->packet_count; i++) {/* Allocate an skb, holding an extra reference for * transmit completion counting */ - skb =alloc_skb (sizeof (state->payload),GFP_KERNEL ); + skb =alloc_skb (EFX_LOOPBACK_PAYLOAD_LEN ,GFP_KERNEL );if (!skb)return -ENOMEM ; state->skbs[i] = skb;
@@ -429,6 +436,8 @@ static int efx_begin_loopback(struct efx_tx_queue *tx_queue) payload =skb_put (skb,sizeof (state->payload));memcpy (payload, &state->payload,sizeof (state->payload)); payload->ip.saddr =htonl (INADDR_LOOPBACK | (i <<2 )); +/* Strip off the leading padding */ +skb_pull (skb, offsetof(struct efx_loopback_payload , header));/* Ensure everything we've written is visible to the * interrupt handler. */
PATCH 3/3 sfc: falcon: use padding to fix alignment in loopback test
In reply to [email protected]From: Edward Cree <[email protected]>
Add two bytes of padding to the start of struct ef4_loopback_payload,
which are not sent on the wire. This ensures the 'ip' member is
4-byte aligned, preventing the following W=1 warning:net/ethernet/sfc/falcon/selftest.c:43:15: error: field ip within 'struct ef4_loopback_payload' is less aligned than 'struct iphdr' and is usually due to 'struct ef4_loopback_payload' being packed, which can lead to unaligned accesses [-Werror,-Wunaligned-access]
struct iphdr ip;
--- drivers/net/ethernet/sfc/falcon/selftest.c | 45 +++++++++++++--------- 1 file changed, 27 insertions(+), 18 deletions(-)
drivers/net/ethernet/sfc/falcon/selftest.c +27 -18
@@ -39,12 +39,16 @@* Falcon only performs RSS on TCP/UDP packets. */ struct ef4_loopback_payload { +char pad[2 ];/* Ensures ip is 4-byte aligned */ struct ethhdr header;struct iphdr ip;struct udphdr udp;__be16 iteration;char msg[64 ]; } __packed; +#define EF4_LOOPBACK_PAYLOAD_LEN (sizeof(struct ef4_loopback_payload) - \ + offsetof(struct ef4_loopback_payload, \ + header))/* Loopback test source MAC address */ static const u8 payload_source[ETH_ALEN ]__aligned(2) = {
@@ -284,7 +288,7 @@ void ef4_loopback_rx_packet(struct ef4_nic *efx, const char *buf_ptr, int pkt_len) {struct ef4_loopback_state *state = efx->loopback_selftest; -struct ef4_loopback_payload *received; +struct ef4_loopback_payload received;struct ef4_loopback_payload *payload;BUG_ON (!buf_ptr);
@@ -295,13 +299,14 @@ void ef4_loopback_rx_packet(struct ef4_nic *efx, payload = &state->payload; - received = (struct ef4_loopback_payload *) buf_ptr; - received->ip.saddr = payload->ip.saddr; +memcpy (&received.header, buf_ptr, +min_t (int, pkt_len,EF4_LOOPBACK_PAYLOAD_LEN )); + received.ip.saddr = payload->ip.saddr;if (state->offload_csum) - received->ip.check = payload->ip.check; + received.ip.check = payload->ip.check;/* Check that header exists */ -if (pkt_len <sizeof (received->header)) { +if (pkt_len <sizeof (received.header)) {netif_err (efx, drv, efx->net_dev,"saw runt RX packet (length %d) in %s loopback " "test\n" , pkt_len,LOOPBACK_MODE (efx));
@@ -309,7 +314,7 @@ void ef4_loopback_rx_packet(struct ef4_nic *efx, }/* Check that the ethernet header exists */ -if (memcmp (&received->header, &payload->header,ETH_HLEN ) !=0 ) { +if (memcmp (&received.header, &payload->header,ETH_HLEN ) !=0 ) {netif_err (efx, drv, efx->net_dev,"saw non-loopback RX packet in %s loopback test\n" ,LOOPBACK_MODE (efx));
@@ -317,16 +322,16 @@ void ef4_loopback_rx_packet(struct ef4_nic *efx, }/* Check packet length */ -if (pkt_len !=sizeof (*payload)) { +if (pkt_len !=EF4_LOOPBACK_PAYLOAD_LEN ) {netif_err (efx, drv, efx->net_dev,"saw incorrect RX packet length %d (wanted %d) in " -"%s loopback test\n" , pkt_len, (int )sizeof (*payload), -LOOPBACK_MODE (efx)); +"%s loopback test\n" , pkt_len, + (int )EF4_LOOPBACK_PAYLOAD_LEN ,LOOPBACK_MODE (efx)); goto err; }/* Check that IP header matches */ -if (memcmp (&received->ip, &payload->ip,sizeof (payload->ip)) !=0 ) { +if (memcmp (&received.ip, &payload->ip,sizeof (payload->ip)) !=0 ) {netif_err (efx, drv, efx->net_dev,"saw corrupted IP header in %s loopback test\n" ,LOOPBACK_MODE (efx));
@@ -334,7 +339,7 @@ void ef4_loopback_rx_packet(struct ef4_nic *efx, }/* Check that msg and padding matches */ -if (memcmp (&received->msg, &payload->msg,sizeof (received->msg)) !=0 ) { +if (memcmp (&received.msg, &payload->msg,sizeof (received.msg)) !=0 ) {netif_err (efx, drv, efx->net_dev,"saw corrupted RX packet in %s loopback test\n" ,LOOPBACK_MODE (efx));
@@ -342,10 +347,10 @@ void ef4_loopback_rx_packet(struct ef4_nic *efx, }/* Check that iteration matches */ -if (received->iteration != payload->iteration) { +if (received.iteration != payload->iteration) {netif_err (efx, drv, efx->net_dev,"saw RX packet from iteration %d (wanted %d) in " -"%s loopback test\n" ,ntohs (received->iteration), +"%s loopback test\n" ,ntohs (received.iteration),ntohs (payload->iteration),LOOPBACK_MODE (efx)); goto err; }
@@ -365,7 +370,8 @@ void ef4_loopback_rx_packet(struct ef4_nic *efx, buf_ptr, pkt_len, 0);netif_err (efx, drv, efx->net_dev,"expected packet:\n" );print_hex_dump (KERN_ERR ,"" ,DUMP_PREFIX_OFFSET ,0x10 ,1 , - &state->payload, sizeof(state->payload), 0); + &state->payload.header,EF4_LOOPBACK_PAYLOAD_LEN , + 0); }#endif atomic_inc (&state->rx_bad);
@@ -387,14 +393,15 @@ static void ef4_iterate_state(struct ef4_nic *efx) payload->ip.daddr =htonl (INADDR_LOOPBACK ); payload->ip.ihl =5 ; payload->ip.check = (__force __sum16 )htons (0xdead ); - payload->ip.tot_len =htons (sizeof (*payload) -sizeof (struct ethhdr )); + payload->ip.tot_len =htons (sizeof (*payload) - + offsetof(struct ef4_loopback_payload , ip)); payload->ip.version =IPVERSION ; payload->ip.protocol =IPPROTO_UDP ;/* Initialise udp header */ payload->udp.source =0 ; - payload->udp.len =htons (sizeof (*payload) -sizeof (struct ethhdr ) - -sizeof (struct iphdr )); + payload->udp.len =htons (sizeof (*payload) - + offsetof(struct ef4_loopback_payload , udp)); payload->udp.check =0 ;/* checksum ignored */ /* Fill out payload */
@@ -420,7 +427,7 @@ static int ef4_begin_loopback(struct ef4_tx_queue *tx_queue)for (i =0 ; i < state->packet_count; i++) {/* Allocate an skb, holding an extra reference for * transmit completion counting */ - skb =alloc_skb (sizeof (state->payload),GFP_KERNEL ); + skb =alloc_skb (EF4_LOOPBACK_PAYLOAD_LEN ,GFP_KERNEL );if (!skb)return -ENOMEM ; state->skbs[i] = skb;
@@ -431,6 +438,8 @@ static int ef4_begin_loopback(struct ef4_tx_queue *tx_queue) payload =skb_put (skb,sizeof (state->payload));memcpy (payload, &state->payload,sizeof (state->payload)); payload->ip.saddr =htonl (INADDR_LOOPBACK | (i <<2 )); +/* Strip off the leading padding */ +skb_pull (skb, offsetof(struct ef4_loopback_payload , header));/* Ensure everything we've written is visible to the * interrupt handler. */