[sctp-dev] SendFailedNotification and fragmentation
Danny
danny at tower.telenet.be
Tue Feb 9 09:46:00 PST 2010
Chris,
As an intro I'd like to synthesize from other SCTP related posts who's
content will be partiality relevant to the problem explained below (for
those reading only this post) that:
- SCTP_EXPLICIT_CONFIRM is support at the SCTP API level, waiting for
lksctp to support SCTP_EXPLICIT_EOR, but a work-around can be used.
- the other fragmentation related socket options (SCTP_DISABLE_FRAGMENTS
and SCTP_FRAGMENT_INTERLEAVE) are already operational and functioning
since earlier lksctp versions
- it is confirmed that situations exist in which send() throws
SocketExceptions when they occur between SHUTDOWN processing at lksctp
level and before ShutdownNotification at application level
Furthermore :
- if they occur after the first part of a non-blocking send() returning
!0 (not 0) and before the effective send would take place on the wire a
SendFailureNotification would occur in stead of a SocketException throw
- the SendFailedNotification object does not have the MessageInfo, as
provided to the send() method, associated with a buffer. It provides
address, association, stream, error and buffer which don't lead to the
related MessageInfo.
Statement :
Given the above, and based on effective working code, i state that it is
possible to implement an asynchronous (non-blocking) class that offers
transparent fragmentation and that can for 100% guarantee that no
message loss will occur between the moment where an application calls a
send() method and the moment that the related data is effectively send
(what wasn't send is returned to the application =100% recovery). There
is however one situation of which i think, or fail to see, that any
implementation that uses the fragmentation features of SCTP will today
and in the future not be able to recover from or provide such a 100%
guarantee, resulting in data loss, unless the interface is adapted some.
Problem:
The specific case is when SendFailedNotification must be handled. These
notification will occur extremely rarely when there is data in the send
buffer while suddenly the socket becomes unfit to write. In that case
one, or more, SendFailedNotifications can be triggered for a same
channel/stream combination depending on how many non-blocking send()'s
have been absorbed into the underlying send buffer, because the buffer
was still sufficiently large to take the message(s) in. This multiple
pending send messages situation is equally the case if a Selector is
used because the SelectionKey will keep getting selected as long as
there is free space in the buffer, unless the application cancels SEND
interest because it has nothing to send anymore.
A robust implementation would need to recover inside a
SendFailureNotification. This is easy and straight forward if the buffer
contains a complete message (not fragmented) because one just has to
bounce it back to the sender with whatever means have been implemented
to do so, but that information is not available at
SendFailureNotification time because it is part of the MessageInfo that
is not provided. However, even worse, if the buffer is a fragment, and
given the fact that in a good implementation the sender should be
fragmentation unaware, the implementation should salvage to complete
message, in order to conform to the SCTP contract on message boundary
guarantee, and then bounce that complete message, and not only that
fragment, to the sender. This means that the implementation must keep
the complete message until the last part is send because relying only on
consecutive SendFailureNotification doesn't guarantee that the complete
message can be re-composed because one doesn't know on what fragment the
first failure occurs and if the rest of the message is already in the
send buffer or not. More, last messages must be kept on a per-stream
basis because the buffer can contain messages for different streams
(the buffers are socket level not stream level) from an application
viewpoint at the moment that the connection or the channel unexpectedly
closes. And as if all this isn't already enough, there could be more
then one fragmented message for a same stream in the buffer which would
imply that the implementation must keep more then the last message per
stream.
Suggestion:
All this brings me to the point to say that, in my opinion and current
state of knowledge, there is a need for some local means (send side)
that makes it possible for code that receives SendFailureNotifications
to access the MessageInfo that was associated with the buffer in the
send() method and preferably with an extra field on the MessageInfo, in
good java tradition an object, that the implementation can use to
associate data. This object should/may not be send to the peer, it is a
local thing in order to stay conform with the SCTP specs and compatible
with other SCTP stacks.
Unfortunately this is only halve the solution because an implementation
that needs to keep messages until they are effectively send on the wire
due to the fact that until that moment a SendFailureNotifcation may
still occur for that message, needs some mechanism to be informed of the
sending in order to do the housekeeping of these kept messages. As far
as i know there is no mechanism that allows to know this at the SCTP API
level (=one that includes the channel/stream number/MessageInfo).
A possible solution could be an overload of the send method taking an
extra argument to provide a notification handler (same type as the one
used for the receive() statement) and add a notification type (eg:
SendReadyNotification or something). If the caller provides the
notification handle object to the send() method then the handler is
called with the SendReadyNotification containing the MessageInfo
(already second parameter of the send() method at this time). If the
caller does not provide the the notification handler then everything
stays as it is today.
I would like feedback on this because i am under the impression that is
is going to be a generic problem, and therefore a generic need, for the
SCTP interface if it is going to be used with the SCTP fragmentation
features as intended to avoid application level (in message or higher
protocol) involvement. I think there may be consensus that the SCTP
fragmentation was intended to perform fragmentations without the need to
know what is in the data buffers (audio, video, text,etc) and without
the need to understand how to recombine it.
Thanks,
Danny
More information about the sctp-dev
mailing list