RX checksum offloading problem

Yonghyeon PYUN pyunyh at gmail.com
Wed May 7 07:56:14 UTC 2014

On Sat, May 03, 2014 at 11:52:47AM +0200, Michael Tuexen wrote:
> On 02 May 2014, at 16:02, Bjoern A. Zeeb <bz at FreeBSD.org> wrote:
> > 
> > On 02 May 2014, at 10:22 , Michael Tuexen <Michael.Tuexen at lurchi.franken.de> wrote:
> > 
> >> Dear all,
> >> 
> >> during testing I found that FreeBSD head (on a raspberry pi) accepts SCTP packet
> >> with bad checksums. After debugging this I figured out that this is a problem with
> >> the csum_flags defined in mbuf.h.
> >> 
> >> The SCTP code on its input path checks for CSUM_SCTP_VALID, which is defined in mbuf.h:
> >> #define CSUM_SCTP_VALID         CSUM_L4_VALID
> >> This makes sense: If CSUM_SCTP_VALID is set in csum_flags, the packet is considered
> >> to have a correct checksum.
> >> 
> >> For UDP and TCP some drivers calculate the UDP/TCP checksum and set CSUM_DATA_VALID in
> >> csum_flags to indicate that the UDP/TCP should consider csum_data to figure out if
> >> the packet has a correct checksum. The problem is that CSUM_DATA_VALID is defined as
> >> #define CSUM_DATA_VALID         CSUM_L4_VALID
> >> In this case the semantic is not that the packet has a valid checksum, but the csum_data
> >> field contains information.
> >> 
> >> Now the following happens (on the raspberry pi the driver used is
> >> dev/usb/net/if_smsc.c
> >> 
> >> 1. A packet is received and if it is not too short, the checksum computed
> >>  is stored in csum_data and the flag CSUM_DATA_VALID is set. This happens
> >>  for all IP packets, not only for UDP and TCP packets.
> >> 2. In case of SCTP packets, the SCTP interprets CSUM_DATA_VALID as CSUM_SCTP_VALID
> >>  and accepts the packet. So no SCTP checksum check ever happened.
> >> 
> >> Alternatives to fix this:
> >> 
> >> 1. Change all drivers to set CSUM_DATA_VALID only in case of UDP or TCP packets, since
> >>  it only makes sense in these cases.
> > 
> > Wait, or for SCTP in cad the crc32 (I think it was)  was actually checked but not otherwise.   This is how it should be imho.  It seems like a driver bug.
> I went through the list of drivers and you are right, it seems to be a bug
> in if_smsc.c. Most of the other drivers check for UDP/TCP, a small set I can't tell.

I'm not sure how the controller computes TCP/UDP checksum values.
It seems the publicly available data sheet was highly sanitized so
it was useless to me.  The comment in the driver says that the
controller computes RX checksum after the IPv4 header to the end of
ethernet frame. After seeing that comment, three questions popped

1. Is the controller smart enough to skip IP options header in
   TCP/UDP checksum offloading?
2. How controller handles UDP checksum value 0x0000(i.e. sender
   didn't compute UDP checksum)?
3. How the controller can compute TCP checksum of fragmented

Since you have the controller I guess it's easy to verify all
cases.  For case 3, I believe the controller can't handle
fragmented frames so driver should have to explicitly check ip_off
field of IPv4 header.  See how gem(4)/sk(4)/hme(4) and fxp(4)
handle it.

> Best regards
> Michael 
> > 
> > 
> > ? 
> > Bjoern A. Zeeb             "Come on. Learn, goddamn it.", WarGames, 1983
> > 
> > 

More information about the freebsd-net mailing list