Subject: SACK Reneging

From: <[email-masked]>
Date: Mon, 18 Jun 2007 12:35:26 -0400 (EDT)

We are investigating a new SCTP related research topic. The investigation is concerned with SACK-reneging (it could apply to both TCP and SCTP).

Can anyone provide any information about or pointers to the following questions:

How often does SACK reneging actually occur in practice?

While RFCs say end-points _must_ be able to handle
a peer doing SACK reneging, do all current OSes in
fact allow SACK reneging to occur?

Could we force SACK reneging on a machine?

Has anyone documented a case where SACK reneging occurs?

Thanks.

Ertugrul Yilmaz
University of Delaware

---

From: "Brian F. G. Bidulock" <[email-masked]>
Date: Mon, 18 Jun 2007 12:47:12 -0600

yilmaz,

On Mon, 18 Jun 2007, [email-masked] wrote:

> We are investigating a new SCTP related research topic. The
> investigation is concerned with SACK-reneging (it could apply to both
> TCP and SCTP).
> 

It is possible to design an SCTP implementation that never renegs.  It
can be a rare occurence or an impossible one depending upon the
implementation.  Randall had some test cases that we used during interop
events to test the ability to respond to a reneg (but generating one was
never a requirement).  Otherwise, I believe only once did we actually
encounter a reneg in interop (and that was due to some other issue).

> 
> While RFCs say end-points _must_ be able to handle a peer doing SACK
> reneging, do all current OSes in fact allow SACK reneging to occur?

The OpenSS7 stacks (Sockets and STREAMS) handle the peer reneging on
SACKs as is required by the specification, only older implementations
will generate a reneg.

> Could we force SACK reneging on a machine?

On previous OpenSS7 SCTP implementation it was possible to force the
receiver to reneg by generating a gap and then filling the receive
window with packets beyond the gap.  The idea being that if the receive
window is full but contains gaps, renegging could be used to free
receive window to allow the sender to continue.

On current OpenSS7 SCTP implementations it is no longer possible to
force the receiver to reneg.  Currently the implementation advertises a
receive window that is less than that used internally by the
implementation.  Rather than renegging, the sender will fill gaps on RTO
and with a zero window probe if necessary.

We did not have zero-window probe clearly stated in the original
specification but it has been stated in the I-G and 2960bis document.
The requirement for the sender to zero-window probe has released the
receiver from ever needing to reneg.  So, in the circumstance above,
a gap followed by a full receive window following the gap will result
in a zero receive window, which must be probed by the sender, and the
sender must eventually send the packet from the gap.

> Has anyone documented a case where SACK reneging occurs?

Err.  I think I just did.  But you will find ample discussion on
sctp-impl mailing list, tsv mailing list and (before it moved sigtran
mailing list) on renegging, and tear-drop attacks for both streams and
segments.

There is a variation of the tear-drop attack for SCTP that goes as
follows:  Send a packet SID 1, SSN 0, TSN 1, DATA 1024 bytes followed
by a packet SID 1, SSN 200,000, TSN 200,001, DATA 1024 bytes and then
addition packets beyond the gap until the receive window is full (i.e.
SID 1, SSN 200,001, TSN 200,002, DATA 1024 bytes, etc.)  Then, when
the receive window is full, start sending packets within the gap but
that do not advance the cummulative ack point (i.e. SID 1, SSN 3, TSN 4,
DATA 1024 bytes, then SID 1, SSN 4, TSN 5, DATA 1024 bytes).  If the
implementation accepts any of these last packets and gap acks them, it
is in trouble.  Additional variations can be performed between multiple
streams, ordered and unordered.

Some implementations have a difficulty in their treatment of a partial
delivery API that requires renegging.  In this case, the first TSN of
segmented data is sent, e.g. SID 1, SSN 0, TSN 1 with B~E and then
SID 1, SSN 0, TSN 3 with ~B~E followed by the remainder of the data
(e.g. say, through to SID 1, SSN 0, TSN 10, ~BE) but sufficient to
fill the receive window.  Then the receiving implementation is in a
position in which it could invoke a partial delivery API for the first
data chunk.  Even if it does, however, a gap can cause the remainder
of the segmented message to fill the receive window.  Now the
implementation can now wait on zero window probe to fill in the missing
data chunks; however, if the implementation refuses to invoke the
partial delivery API (and waits for all segments), it must either
exceed its receive buffer allocation (dangerous because of tear-drop
attacks) or needs to reneg on some of the later segments to free receive
buffer.

OpenSS7 implementations circumvent this arrangement by always invoking
partial delivery API and waiting on zero window probe to advance the
cummulative ack point.

Hope that helps.

--brian

-- 
Brian F. G. Bidulock    ¦ The reasonable man adapts himself to the ¦
[email-masked]    ¦ world; the unreasonable one persists in  ¦
http://www.openss7.org/ ¦ trying  to adapt the  world  to himself. ¦
                        ¦ Therefore  all  progress  depends on the ¦
                        ¦ unreasonable man. -- George Bernard Shaw ¦