• Daniel Borkmann's avatar
    net: sctp: wake up all assocs if sndbuf policy is per socket · 52c35bef
    Daniel Borkmann authored
    SCTP charges chunks for wmem accounting via skb->truesize in
    sctp_set_owner_w(), and sctp_wfree() respectively as the
    reverse operation. If a sender runs out of wmem, it needs to
    wait via sctp_wait_for_sndbuf(), and gets woken up by a call
    to __sctp_write_space() mostly via sctp_wfree().
    
    __sctp_write_space() is being called per association. Although
    we assign sk->sk_write_space() to sctp_write_space(), which
    is then being done per socket, it is only used if send space
    is increased per socket option (SO_SNDBUF), as SOCK_USE_WRITE_QUEUE
    is set and therefore not invoked in sock_wfree().
    
    Commit 4c3a5bda ("sctp: Don't charge for data in sndbuf
    again when transmitting packet") fixed an issue where in case
    sctp_packet_transmit() manages to queue up more than sndbuf
    bytes, sctp_wait_for_sndbuf() will never be woken up again
    unless it is interrupted by a signal. However, a still
    remaining issue is that if net.sctp.sndbuf_policy=0, that is
    accounting per socket, and one-to-many sockets are in use,
    the reclaimed write space from sctp_wfree() is 'unfairly'
    handed back on the server to the association that is the lucky
    one to be woken up again via __sctp_write_space(), while
    the remaining associations are never be woken up again
    (unless by a signal).
    
    The effect disappears with net.sctp.sndbuf_policy=1, that
    is wmem accounting per association, as it guarantees a fair
    share of wmem among associations.
    
    Therefore, if we have reclaimed memory in case of per socket
    accounting, wake all related associations to a socket in a
    fair manner, that is, traverse the socket association list
    starting from the current neighbour of the association and
    issue a __sctp_write_space() to everyone until we end up
    waking ourselves. This guarantees that no association is
    preferred over another and even if more associations are
    taken into the one-to-many session, all receivers will get
    messages from the server and are not stalled forever on
    high load. This setting still leaves the advantage of per
    socket accounting in touch as an association can still use
    up global limits if unused by others.
    
    Fixes: 4eb701df ("[SCTP] Fix SCTP sendbuffer accouting.")
    Signed-off-by: default avatarDaniel Borkmann <dborkman@redhat.com>
    Cc: Thomas Graf <tgraf@suug.ch>
    Cc: Neil Horman <nhorman@tuxdriver.com>
    Cc: Vlad Yasevich <vyasevic@redhat.com>
    Acked-by: default avatarVlad Yasevich <vyasevic@redhat.com>
    Acked-by: default avatarNeil Horman <nhorman@tuxdriver.com>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    52c35bef
socket.c 201 KB