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

Bug#608144: linux-image-2.6.32-5-xen-amd64: Kernel oops: net/core/dev.c:1582 skb_gso_segment+0x109/0x263() (Bug #596802 reappeared)



On Tue, Jan 04, 2011 at 10:08:32PM +0000, Ian Campbell wrote:
> On Tue, 2011-01-04 at 21:44 +0100, Stephan Austermühle wrote: 
> > So the problem was already present in -23 and it just seems to have the
> > same symptoms like #596802.
> 
> OK, thanks for testing that.
> 
> I wonder if you could play with ethtool to enable/disable various
> features on the physical NIC. In particular I think it might be worth
> fiddling with the LRO and GRO settings, via the -k/-K options.

I don't think this has anything to do with the physical NIC.  LRO is
automatically turned off for interfaces that are connected to a bridge,
and GRO is safe with bridging.

> The reason for this is that the warning you are seeing is because the
> skb in question has skb->gso_size != 0 (i.e. it is apparently a GSO skb)
> but it is not skb->ip_summed == CHECKSUM_PARTIAL, which is necessary in
> order to do GSO, (i.e. to send the SKB).

It's not so much necessary as the only valid possibility for an skb that
requires GSO.  On output an skb must have ip_summed = CHECKSUM_NONE (not
to be checksummed) or ip_summed = CHECKSUM_PARTIAL (checksum to be
calculated by hardware or software).  But here we see ip_summed =
CHECKSUM_UNNECESSSARY which is only meaningful on input.

So, I think what's happening here is:
1. The Windows PVHVM driver claims to support checksum offload and TSO.
   Windows passes it oversized packets with no checksum information.
2. netback receives these oversized packets and sets gso_size on the skb
   just as if they were received with LRO or GRO.  Since the packet does
   not have valid checksums either in-band or out-of-band, it labels the
   skb with ip_summed = CHECKSUM_UNNECESSARY.

On Linux the stack always calculates the IPv4 checksum and the TCP/UDP
pseudo-header checksum (ip_summed = CHECKSUMMED_PARTIAL refers to this
partial checksum information).  For packets received from a Linux guest,
netback will label the skb accordingly and GSO is happy.

netback needs to fix up the checksum information for packets that the
guest sent with TSO and no checksum:
1. Calculate the IPv4 header checksum and write it to the packet buffer
   (not for IPv6, obviously).
2. Calculate the TCP/UDP pseudo-header checksum and store it in skb->csum.
3. Set skb->csum_start and skb->csum_offset per kernel-doc.
4. Set skb->ip_summed = CHECKSUM_PARTIAL.

> I think one way that such skbs can be injected into the system is via
> LRO on the physical NIC (LRO is a bit like, but not exactly identical
> to, the opposite of GSO, AIUI). When an NIC which supports LRO is
> bridged then these SKBs are passed across the bridge and end up getting
> treated as GSO on the outgoing path (i.e. the VIF) even though they
> aren't quite GSO frames, and this triggers the warning in
> skb_gso_segment.
> 
> GRO is a generalisation of LRO, I'm not sure if it is supposed to fix
> this forwarding issue or not.
 
GRO is a specific software implementation of LRO that preserves enough
information that it is safe to bridge/forward the resulting skb.  The
original packets can be reconstructed on transmit (usually through TSO,
otherwise through GSO).

Ben.

-- 
Ben Hutchings
We get into the habit of living before acquiring the habit of thinking.
                                                              - Albert Camus



Reply to: