[Bug 260114] [sctp] SO_SNDLOWAT is not accounted for when sending data

From: <bugzilla-noreply_at_freebsd.org>
Date: Mon, 29 Nov 2021 12:51:03 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=260114

            Bug ID: 260114
           Summary: [sctp] SO_SNDLOWAT is not accounted for when sending
                    data
           Product: Base System
           Version: 13.0-RELEASE
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Some People
          Priority: ---
         Component: kern
          Assignee: bugs@FreeBSD.org
          Reporter: albin.hellqvist@gmail.com

When sending data over SCTP and using e.g., sctp_sendv(), SO_SNDLOWAT is not
accounted for.

For example, let's say that I have a socket send buffer of 32768 bytes and I
have set SO_SNDLOWAT to 10000 bytes. If the send buffer is filled up to say
25000 bytes, then I shouldn't be able to send anything until there are
SO_SNDLOWAT (1000) amount of bytes (+ 1?) bytes free in the socket send buffer.

From (https://www.freebsd.org/cgi/man.cgi?query=setsockopt&sektion=2):
SO_SNDLOWAT is an option to set the minimum count for output operations. Most
output operations process all of the data supplied by the call, delivering data
to the protocol for transmission and blocking as necessary for flow control.   
  Nonblocking output operations will process as much data as permitted subject
to flow control without blocking, but will process no data if flow control does
not allow the smaller of the low water mark value or the entire request to be
processed.

This has been tested on FreeBSD 12.2-RELEASE and FreeBSD 13.0-RELEASE as well
as on Linux (lksctp). The FreeBSD releases have the same behavior while it
works in Linux.

I have only tested this for non-blocking sockets so I don't know the behavior
of blocking sockets. I guess it should block until the same criterion has
happened.

At least for non-blocking sockets, I believe that this can be fixed by adding a
line in the sctp_lower_sosend() function in (sys/netinet/sctp_output.c).

More specifically, these lines can be changed:
if ((SCTP_SB_LIMIT_SND(so) < (amount + inqueue_bytes +
stcb->asoc.sb_send_resv)) ||
    (stcb->asoc.chunks_on_out_queue >=
SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue))) {

To include this (or something similar):
|| (so->so_snd.sb_hiwat - so->so_snd.sb_acc) <= (u_int)so->so_snd.sb_lowat)

Sorry for not uploading a patch, but I am unsure if my fix is of use or not.

-- 
You are receiving this mail because:
You are the assignee for the bug.