Pantek Library
Hosting Provided By
CybrHost
High Speed Hosting

kernel/3319: hardware datagram checksumming vs. IP fragmentation

From: <gwes(at)oat.com>
Date: Mon Jun 16 2003 - 20:19:58 EDT


>Number: 3319
>Category: kernel
>Synopsis: hardware checksum can cause good IP fragments to be dropped
>Confidential: no

Geoff Steckel, Owner      gwes@oat.com
Omnivore Technology       +1 617 332 9252
127 Cornell St.
Newton, MA 02462
>Environment:
	i386/3.2 or i386/3.3 with DGE (possibly other interfaces)
	System      : OpenBSD 3.2
	Architecture: OpenBSD.i386
	Machine     : i386

>Description:
The dge interface can perform hardware checksumming of incoming TCP and UDP over IP packets. The higher level protocol's checksum is by definition unknown until all fragments have been received. The dge doesn't check ip_off. This causes essentially all fragmented UDP datagrams to be dropped. Since many versions of TCP attempt to avoid fragmentation, the problem is not as obvious. The most obvious usage affected is NFS. It uses up to 8K or 32K datagrams, which are always fragmented by ethernet-like physical layers.
>How-To-Repeat:
On a client machine connected via a DGE interface, NFS mount a file system containing a large directory. Attempt to ls that directory. The ls will never succeed, and the counters for IP hardware checksum errors will increase for every NFS retransmit.

>Fix:

Since fragmentation is often a source of subtle bugs, the fix is applied at the IP level, not in the driver. By definition the driver cannot know the TCP or UDP checksum, so clear the bits in m_pkthdr.csum for all incoming fragmented IP datagrams.

in 3.2 code base, at ip_input.c line 535, ipv4_input(m), just after the label "ours:"

  • Otherwise, nothing need be done.
  • (We could look in the reassembly queue to see
  • if the packet was previously fragmented,
  • but it's not worth the time; just let them time out.) */ if (ip->ip_off &~ (IP_DF | IP_RF)) { + /* Don't believe hardware higher protocol checksum on fragments */ + m->m_pkthdr.csum &= + ~ (M_TCP_CSUM_IN_OK | M_TCP_CSUM_IN_BAD + | M_UDP_CSUM_IN_OK | M_UDP_CSUM_IN_BAD); if (m->m_flags & M_EXT) { /* XXX */ if ((m = m_pullup(m, hlen)) == NULL) { ipstat.ips_toosmall++;

>Release-Note:
Received on Mon Jun 16 20:45:27 2003

This archive was generated by hypermail 2.1.8 : Wed Aug 23 2006 - 13:29:58 EDT


Contact Us  Legal Notices  Order Services Online 
Pantek Home  Privacy Policy  IT news  Site Map  Pantek Library