From b3690ea4dad191b613b526d4cb4bc0d985929403 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Svensson?= Date: Tue, 25 Jan 2022 10:35:30 +0000 Subject: [PATCH] Handle POLLOUT/EVFILT_WRITE when send buffer is full Since the socket buffer counter sb_cc has been split into sb_ccc and sb_acc, and both are used, there is a need to update both counters. Currently sb_acc is used as sb_cc to enable select(), but sb_ccc is required to be updated as well for the poll events and Kqueue filters. This adds a macro for unifying the sb_acc and sb_ccc counters when there is a need to update the value. The macro can be changed for upstream users in a similar way as for the use of sb_cc, i.e. it can be disabled when there is a need to keep the old way of only using sb_cc. --- sys/netinet/sctp_input.c | 1 + sys/netinet/sctp_os_bsd.h | 7 ++++++- sys/netinet/sctp_output.c | 1 + sys/netinet/sctp_structs.h | 1 + sys/netinet/sctp_usrreq.c | 1 + sys/netinet/sctp_var.h | 4 ++++ sys/netinet/sctputil.c | 2 ++ sys/netinet/sctputil.h | 3 +++ 8 files changed, 19 insertions(+), 1 deletion(-) diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c index ce017b74b67..34f162db5e0 100644 --- a/sys/netinet/sctp_input.c +++ b/sys/netinet/sctp_input.c @@ -995,6 +995,7 @@ sctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp SCTP_UNUSED, if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { stcb->sctp_socket->so_snd.sb_cc = 0; + SCTP_UNIFY_SB_CC(&stcb->sctp_socket->so_snd); } sctp_ulp_notify(SCTP_NOTIFY_ASSOC_DOWN, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); } diff --git a/sys/netinet/sctp_os_bsd.h b/sys/netinet/sctp_os_bsd.h index 39c0a8cb5c2..159ba58a52c 100644 --- a/sys/netinet/sctp_os_bsd.h +++ b/sys/netinet/sctp_os_bsd.h @@ -378,6 +378,10 @@ typedef struct callout sctp_os_timer_t; * with SCTP sockets. */ #define sb_cc sb_acc +/* Since both sb_acc and sb_ccc are used by the framework we need + * to make sure the values are unified, e.g. POLL/EVFILT uses sb_ccc. + */ +#define SCTP_UNIFY_SB_CC(sb) (atomic_store_int(&(sb)->sb_ccc, (sb)->sb_acc)) /* reserve sb space for a socket */ #define SCTP_SORESERVE(so, send, recv) soreserve(so, send, recv) /* wakeup a socket */ @@ -386,7 +390,8 @@ typedef struct callout sctp_os_timer_t; #define SCTP_SB_CLEAR(sb) \ (sb).sb_cc = 0; \ (sb).sb_mb = NULL; \ - (sb).sb_mbcnt = 0; + (sb).sb_mbcnt = 0; \ + SCTP_UNIFY_SB_CC(&sb); #define SCTP_SB_LIMIT_RCV(so) (SOLISTENING(so) ? so->sol_sbrcv_hiwat : so->so_rcv.sb_hiwat) #define SCTP_SB_LIMIT_SND(so) (SOLISTENING(so) ? so->sol_sbsnd_hiwat : so->so_snd.sb_hiwat) diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index 277a6625aa1..66f81eeb016 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -7258,6 +7258,7 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb, ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL))) { atomic_subtract_int(&stcb->sctp_socket->so_snd.sb_cc, sp->length); + SCTP_UNIFY_SB_CC(&stcb->sctp_socket->so_snd); } if (sp->data) { sctp_m_freem(sp->data); diff --git a/sys/netinet/sctp_structs.h b/sys/netinet/sctp_structs.h index a22dac04797..2af2661dc4c 100644 --- a/sys/netinet/sctp_structs.h +++ b/sys/netinet/sctp_structs.h @@ -1003,6 +1003,7 @@ struct sctp_association { uint32_t total_output_queue_size; uint32_t sb_cc; /* shadow of sb_cc */ + uint32_t sb_ccc; /* shadow of sb_ccc */ uint32_t sb_send_resv; /* amount reserved on a send */ uint32_t my_rwnd_control_len; /* shadow of sb_mbcnt used for rwnd * control */ diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c index 2dad0b41a30..3109830f76a 100644 --- a/sys/netinet/sctp_usrreq.c +++ b/sys/netinet/sctp_usrreq.c @@ -838,6 +838,7 @@ sctp_flush(struct socket *so, int how) * except maybe the count */ so->so_snd.sb_cc = 0; + SCTP_UNIFY_SB_CC(&so->so_snd); so->so_snd.sb_mbcnt = 0; so->so_snd.sb_mb = NULL; } diff --git a/sys/netinet/sctp_var.h b/sys/netinet/sctp_var.h index ed01de7d701..2ca5501fa2a 100644 --- a/sys/netinet/sctp_var.h +++ b/sys/netinet/sctp_var.h @@ -199,9 +199,11 @@ extern struct pr_usrreqs sctp_usrreqs; #define sctp_sbfree(ctl, stcb, sb, m) { \ SCTP_SAVE_ATOMIC_DECREMENT(&(sb)->sb_cc, SCTP_BUF_LEN((m))); \ + SCTP_UNIFY_SB_CC(sb); \ SCTP_SAVE_ATOMIC_DECREMENT(&(sb)->sb_mbcnt, MSIZE); \ if (((ctl)->do_not_ref_stcb == 0) && stcb) {\ SCTP_SAVE_ATOMIC_DECREMENT(&(stcb)->asoc.sb_cc, SCTP_BUF_LEN((m))); \ + SCTP_UNIFY_SB_CC(&(stcb)->asoc); \ SCTP_SAVE_ATOMIC_DECREMENT(&(stcb)->asoc.my_rwnd_control_len, MSIZE); \ } \ if (SCTP_BUF_TYPE(m) != MT_DATA && SCTP_BUF_TYPE(m) != MT_HEADER && \ @@ -211,9 +213,11 @@ extern struct pr_usrreqs sctp_usrreqs; #define sctp_sballoc(stcb, sb, m) { \ atomic_add_int(&(sb)->sb_cc,SCTP_BUF_LEN((m))); \ + SCTP_UNIFY_SB_CC(sb); \ atomic_add_int(&(sb)->sb_mbcnt, MSIZE); \ if (stcb) { \ atomic_add_int(&(stcb)->asoc.sb_cc, SCTP_BUF_LEN((m))); \ + SCTP_UNIFY_SB_CC(&(stcb)->asoc); \ atomic_add_int(&(stcb)->asoc.my_rwnd_control_len, MSIZE); \ } \ if (SCTP_BUF_TYPE(m) != MT_DATA && SCTP_BUF_TYPE(m) != MT_HEADER && \ diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c index 42e91e10a0d..a96b01d95e2 100644 --- a/sys/netinet/sctputil.c +++ b/sys/netinet/sctputil.c @@ -5045,6 +5045,7 @@ sctp_free_bufspace(struct sctp_tcb *stcb, struct sctp_association *asoc, } else { stcb->sctp_socket->so_snd.sb_cc = 0; } + SCTP_UNIFY_SB_CC(&stcb->sctp_socket->so_snd); } } @@ -6127,6 +6128,7 @@ sctp_sorecvmsg(struct socket *so, if ((control->do_not_ref_stcb == 0) && stcb) { atomic_subtract_int(&stcb->asoc.sb_cc, cp_len); + SCTP_UNIFY_SB_CC(&stcb->asoc); } copied_so_far += cp_len; freed_so_far += (uint32_t)cp_len; diff --git a/sys/netinet/sctputil.h b/sys/netinet/sctputil.h index 3319eb4f455..8e8b8749860 100644 --- a/sys/netinet/sctputil.h +++ b/sys/netinet/sctputil.h @@ -264,6 +264,7 @@ do { \ } else { \ stcb->sctp_socket->so_snd.sb_cc = 0; \ } \ + SCTP_UNIFY_SB_CC(&stcb->sctp_socket->so_snd); \ } \ } \ } while (0) @@ -285,6 +286,7 @@ do { \ } else { \ stcb->sctp_socket->so_snd.sb_cc = 0; \ } \ + SCTP_UNIFY_SB_CC(&stcb->sctp_socket->so_snd); \ } \ } \ } while (0) @@ -296,6 +298,7 @@ do { \ ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || \ (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL))) { \ atomic_add_int(&stcb->sctp_socket->so_snd.sb_cc,sz); \ + SCTP_UNIFY_SB_CC(&stcb->sctp_socket->so_snd); \ } \ } while (0) -- 2.34.1