Bug 806 - TCP doesn't work over a CSMA link
TCP doesn't work over a CSMA link
Status: RESOLVED FIXED
Product: ns-3
Classification: Unclassified
Component: internet
ns-3.7
All All
: P1 critical
Assigned To: ns-bugs
:
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2010-02-04 13:02 EST by Bill Roome
Modified: 2010-02-09 02:02 EST (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Bill Roome 2010-02-04 13:02:50 EST
Basically, TCP does not work over a CSMA link. Period.

The problem: In 3.7, csma_net_device.cc enforces the rule that e'net packets must have a minimum of 46 bytes of payload. It does so by padding short packets with zeros.

This shouldn't be a problem, because the IP header has a length field, so the stack should just ignore the extra padding. However, when the IP layer removes the IP header from the packet and passes the remainder on to the TCP layer, the IP layer doesn't pass the payload length to TCP. Instead, TCP assumes everything left in the packet is valid data.

The result: when one end sends a simple ACK (40 bytes of IP+TCP headers, no application data), CSMA appends 6 bytes of zeros. The TCP stack on the other end assumes those 6 bytes are application data, and tries to pass them up to the application on its end. The result is much confusion.

One solution: When the IP layer strips the IP header from a packet, if the resulting packet size is greater than the payload length, the IP layer could remove the extra bytes from the end of the packet.

I don't know all the places that's necessary, but one is in Ipv4L3Protocol::Receive() in ipv4-l3-protocol.cc. To test, I added the following after the RemoveHeader() call:

    // Existing code -- line 459 in ipv4-l3-protocol.cc, 3.7 Stable:
  packet->RemoveHeader (ipHeader);

    // Added:
  if (ipHeader.GetPayloadSize () < packet->GetSize ())
    {
      packet->RemoveAtEnd (packet->GetSize () - ipHeader.GetPayloadSize ());
    }

After that, TCP worked properly over a CSMA link.
Comment 1 Tom Henderson 2010-02-05 19:23:53 EST
(In reply to comment #0)
> Basically, TCP does not work over a CSMA link. Period.
> 
> The problem: In 3.7, csma_net_device.cc enforces the rule that e'net packets
> must have a minimum of 46 bytes of payload. It does so by padding short packets
> with zeros.
> 
> This shouldn't be a problem, because the IP header has a length field, so the
> stack should just ignore the extra padding. However, when the IP layer removes
> the IP header from the packet and passes the remainder on to the TCP layer, the
> IP layer doesn't pass the payload length to TCP. Instead, TCP assumes
> everything left in the packet is valid data.
> 
> The result: when one end sends a simple ACK (40 bytes of IP+TCP headers, no
> application data), CSMA appends 6 bytes of zeros. The TCP stack on the other
> end assumes those 6 bytes are application data, and tries to pass them up to
> the application on its end. The result is much confusion.
> 
> One solution: When the IP layer strips the IP header from a packet, if the
> resulting packet size is greater than the payload length, the IP layer could
> remove the extra bytes from the end of the packet.
> 
> I don't know all the places that's necessary, but one is in
> Ipv4L3Protocol::Receive() in ipv4-l3-protocol.cc. To test, I added the
> following after the RemoveHeader() call:
> 
>     // Existing code -- line 459 in ipv4-l3-protocol.cc, 3.7 Stable:
>   packet->RemoveHeader (ipHeader);
> 
>     // Added:
>   if (ipHeader.GetPayloadSize () < packet->GetSize ())
>     {
>       packet->RemoveAtEnd (packet->GetSize () - ipHeader.GetPayloadSize ());
>     }
> 
> After that, TCP worked properly over a CSMA link.

Your solution is also what BSD does (see Stevens Vol. II p. 216), so I would like to fix this similarly for both IPv4 and IPv6.

This bug was probably introduced in early December when CsmaNetDevice was padded out to 46 bytes as necessary, so probably only affects ns-3.7 release.
Comment 2 Tom Henderson 2010-02-08 03:21:47 EST
(In reply to comment #1)
> (In reply to comment #0)
> > Basically, TCP does not work over a CSMA link. Period.
> > 
> > The problem: In 3.7, csma_net_device.cc enforces the rule that e'net packets
> > must have a minimum of 46 bytes of payload. It does so by padding short packets
> > with zeros.
> > 
> > This shouldn't be a problem, because the IP header has a length field, so the
> > stack should just ignore the extra padding. However, when the IP layer removes
> > the IP header from the packet and passes the remainder on to the TCP layer, the
> > IP layer doesn't pass the payload length to TCP. Instead, TCP assumes
> > everything left in the packet is valid data.
> > 
> > The result: when one end sends a simple ACK (40 bytes of IP+TCP headers, no
> > application data), CSMA appends 6 bytes of zeros. The TCP stack on the other
> > end assumes those 6 bytes are application data, and tries to pass them up to
> > the application on its end. The result is much confusion.
> > 
> > One solution: When the IP layer strips the IP header from a packet, if the
> > resulting packet size is greater than the payload length, the IP layer could
> > remove the extra bytes from the end of the packet.
> > 
> > I don't know all the places that's necessary, but one is in
> > Ipv4L3Protocol::Receive() in ipv4-l3-protocol.cc. To test, I added the
> > following after the RemoveHeader() call:
> > 
> >     // Existing code -- line 459 in ipv4-l3-protocol.cc, 3.7 Stable:
> >   packet->RemoveHeader (ipHeader);
> > 
> >     // Added:
> >   if (ipHeader.GetPayloadSize () < packet->GetSize ())
> >     {
> >       packet->RemoveAtEnd (packet->GetSize () - ipHeader.GetPayloadSize ());
> >     }
> > 
> > After that, TCP worked properly over a CSMA link.
> 
> Your solution is also what BSD does (see Stevens Vol. II p. 216), so I would
> like to fix this similarly for both IPv4 and IPv6.
> 
> This bug was probably introduced in early December when CsmaNetDevice was
> padded out to 46 bytes as necessary, so probably only affects ns-3.7 release.


I will check in a fix to this once I finish a small test suite for this.
Comment 3 Tom Henderson 2010-02-09 02:02:01 EST
changeset: 288416b082a4
test ns3-tcp-socket exercises this code path