The branch main has been updated by tuexen:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=d9ae4adff2715cfab4a941037ec15aa07108efa1

commit d9ae4adff2715cfab4a941037ec15aa07108efa1
Author:     Michael Tuexen <tue...@freebsd.org>
AuthorDate: 2023-05-03 15:30:50 +0000
Commit:     Michael Tuexen <tue...@freebsd.org>
CommitDate: 2023-05-03 15:33:49 +0000

    sctp: improve shutdown(..., SHUT_WR) handling
    
    When shutdown(..., SHUT_WR) is called in the front states, send a
    SHUTDOWN chunk when a COOKIE ACK chunk is received and there is
    no outstanding data.
    
    MFC after:      1 week
---
 sys/netinet/sctp_input.c | 22 ++++++++++++++++------
 1 file changed, 16 insertions(+), 6 deletions(-)

diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c
index 26abf4953164..fc362d091a22 100644
--- a/sys/netinet/sctp_input.c
+++ b/sys/netinet/sctp_input.c
@@ -2782,16 +2782,13 @@ sctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp 
SCTP_UNUSED,
                    __LINE__);
        }
        sctp_stop_all_cookie_timers(stcb);
+       sctp_toss_old_cookies(stcb, asoc);
        /* process according to association state */
        if (SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_ECHOED) {
                /* state change only needed when I am in right state */
                SCTPDBG(SCTP_DEBUG_INPUT2, "moving to OPEN state\n");
                SCTP_SET_STATE(stcb, SCTP_STATE_OPEN);
                sctp_start_net_timers(stcb);
-               if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
-                       sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
-                           stcb->sctp_ep, stcb, NULL);
-               }
                /* update RTO */
                SCTP_STAT_INCR_COUNTER32(sctps_activeestab);
                SCTP_STAT_INCR_GAUGE32(sctps_currestab);
@@ -2815,6 +2812,21 @@ sctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp 
SCTP_UNUSED,
                        }
                }
 
+               if ((asoc->state & SCTP_STATE_SHUTDOWN_PENDING) &&
+                   TAILQ_EMPTY(&asoc->send_queue) &&
+                   TAILQ_EMPTY(&asoc->sent_queue) &&
+                   (asoc->stream_queue_cnt == 0)) {
+                       SCTP_STAT_DECR_GAUGE32(sctps_currestab);
+                       SCTP_SET_STATE(stcb, SCTP_STATE_SHUTDOWN_SENT);
+                       sctp_stop_timers_for_shutdown(stcb);
+                       sctp_send_shutdown(stcb, net);
+                       sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
+                           stcb->sctp_ep, stcb, net);
+                       sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
+                           stcb->sctp_ep, stcb, NULL);
+                       sctp_chunk_output(stcb->sctp_ep, stcb, 
SCTP_OUTPUT_FROM_T3, SCTP_SO_LOCKED);
+               }
+
                if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
                        /*
                         * We don't need to do the asconf thing, nor hb or
@@ -2850,8 +2862,6 @@ sctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp 
SCTP_UNUSED,
                }
        }
 closed_socket:
-       /* Toss the cookie if I can */
-       sctp_toss_old_cookies(stcb, asoc);
        /* Restart the timer if we have pending data */
        TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) {
                if (chk->whoTo != NULL) {

Reply via email to