Skip to content

Commit

Permalink
forcedeth: checksum fix
Browse files Browse the repository at this point in the history
The driver should inform the stack when checksum has been performed by
the HW when both IP and TCP (or UDP) checksum flags are indicated by HW.

Previously, it would also inform the stack when only IP checksum flag
was indicated by HW. This can cause data corruption when IP fragments
are used. The IP Identification field can wrap around and cause data
from new fragments to fill into older fragment slots with same IP Id.
The stack would then not perform TCP/UDP checksum (after re-assembly of
all fragments) since driver falsely stated it was already calculated.

Signed-off-by: Ayaz Abdulla <aabdulla@nvidia.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Ayaz Abdulla authored and David S. Miller committed Feb 3, 2008
1 parent 0a62677 commit bfaffe8
Showing 1 changed file with 7 additions and 17 deletions.
24 changes: 7 additions & 17 deletions drivers/net/forcedeth.c
Original file line number Diff line number Diff line change
Expand Up @@ -471,9 +471,9 @@ union ring_type {
#define NV_RX_AVAIL (1<<31)

#define NV_RX2_CHECKSUMMASK (0x1C000000)
#define NV_RX2_CHECKSUMOK1 (0x10000000)
#define NV_RX2_CHECKSUMOK2 (0x14000000)
#define NV_RX2_CHECKSUMOK3 (0x18000000)
#define NV_RX2_CHECKSUM_IP (0x10000000)
#define NV_RX2_CHECKSUM_IP_TCP (0x14000000)
#define NV_RX2_CHECKSUM_IP_UDP (0x18000000)
#define NV_RX2_DESCRIPTORVALID (1<<29)
#define NV_RX2_SUBSTRACT1 (1<<25)
#define NV_RX2_ERROR1 (1<<18)
Expand Down Expand Up @@ -2375,14 +2375,9 @@ static int nv_rx_process(struct net_device *dev, int limit)
goto next_pkt;
}
}
if ((flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUMOK2)/*ip and tcp */ {
if (((flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUM_IP_TCP) || /*ip and tcp */
((flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUM_IP_UDP)) /*ip and udp */
skb->ip_summed = CHECKSUM_UNNECESSARY;
} else {
if ((flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUMOK1 ||
(flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUMOK3) {
skb->ip_summed = CHECKSUM_UNNECESSARY;
}
}
} else {
dev_kfree_skb(skb);
goto next_pkt;
Expand Down Expand Up @@ -2474,14 +2469,9 @@ static int nv_rx_process_optimized(struct net_device *dev, int limit)
}
}

if ((flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUMOK2)/*ip and tcp */ {
if (((flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUM_IP_TCP) || /*ip and tcp */
((flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUM_IP_UDP)) /*ip and udp */
skb->ip_summed = CHECKSUM_UNNECESSARY;
} else {
if ((flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUMOK1 ||
(flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUMOK3) {
skb->ip_summed = CHECKSUM_UNNECESSARY;
}
}

/* got a valid packet - forward it to the network core */
skb_put(skb, len);
Expand Down

0 comments on commit bfaffe8

Please sign in to comment.