diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index 360b7b56cee..7f5e70d14e9 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -800,7 +800,7 @@ sonewconn(struct socket *head, int connstatus) return (NULL); } - solisten_enqueue(so, connstatus); + (void)solisten_enqueue(so, connstatus); return (so); } @@ -808,8 +808,10 @@ sonewconn(struct socket *head, int connstatus) /* * Enqueue socket cloned by solisten_clone() to the listen queue of the * listener it has been cloned from. + * + * Return 'true' if socket landed on complete queue, otherwise 'false'. */ -void +bool solisten_enqueue(struct socket *so, int connstatus) { struct socket *head = so->so_listen; @@ -827,6 +829,7 @@ solisten_enqueue(struct socket *so, int connstatus) so->so_qstate = SQ_COMP; head->sol_qlen++; solisten_wakeup(head); /* unlocks */ + return (true); } else { /* * Keep removing sockets from the head until there's room for @@ -853,6 +856,7 @@ solisten_enqueue(struct socket *so, int connstatus) so->so_qstate = SQ_INCOMP; head->sol_incqlen++; SOLISTEN_UNLOCK(head); + return (false); } } diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index e8f2676f2aa..86071141b17 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -2433,7 +2433,10 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, case TCPS_SYN_RECEIVED: TCPSTAT_INC(tcps_connects); - soisconnected(so); + if (tp->t_flags & TF_INCQUEUE) { + tp->t_flags &= ~TF_INCQUEUE; + soisconnected(so); + } /* Do window scaling? */ if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) == (TF_RCVD_SCALE|TF_REQ_SCALE)) { diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c index 76272179dac..f0ee539fa1e 100644 --- a/sys/netinet/tcp_syncache.c +++ b/sys/netinet/tcp_syncache.c @@ -1039,7 +1039,8 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m) TCPSTAT_INC(tcps_accepts); TCP_PROBE6(state__change, NULL, tp, NULL, tp, NULL, TCPS_LISTEN); - solisten_enqueue(so, SS_ISCONNECTED); + if (!solisten_enqueue(so, SS_ISCONNECTED)) + tp->t_flags |= TF_INCQUEUE; return (so); diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index d1b7ce5daa6..474cdb4d778 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -2978,8 +2978,8 @@ db_print_tflags(u_int t_flags) db_printf("%sTF_MORETOCOME", comma ? ", " : ""); comma = 1; } - if (t_flags & TF_LQ_OVERFLOW) { - db_printf("%sTF_LQ_OVERFLOW", comma ? ", " : ""); + if (t_flags & TF_INCQUEUE) { + db_printf("%sTF_INCQUEUE", comma ? ", " : ""); comma = 1; } if (t_flags & TF_LASTIDLE) { diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h index 20bf72dcd9d..6019f162090 100644 --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -515,7 +515,7 @@ tcp_unlock_or_drop(struct tcpcb *tp, int tcp_output_retval) #define TF_WAKESOR 0x00004000 /* wake up receive socket */ #define TF_GPUTINPROG 0x00008000 /* Goodput measurement in progress */ #define TF_MORETOCOME 0x00010000 /* More data to be appended to sock */ -#define TF_LQ_OVERFLOW 0x00020000 /* listen queue overflow */ +#define TF_INCQUEUE 0x00020000 /* on incomplete queue of listener */ #define TF_LASTIDLE 0x00040000 /* connection was previously idle */ #define TF_RXWIN0SENT 0x00080000 /* sent a receiver win 0 in response */ #define TF_FASTRECOVERY 0x00100000 /* in NewReno Fast Recovery */ diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h index 678642eeff6..0c60b9e13cf 100644 --- a/sys/sys/socketvar.h +++ b/sys/sys/socketvar.h @@ -474,7 +474,7 @@ int solisten(struct socket *so, int backlog, struct thread *td); void solisten_proto(struct socket *so, int backlog); void solisten_proto_abort(struct socket *so); int solisten_proto_check(struct socket *so); -void solisten_enqueue(struct socket *, int); +bool solisten_enqueue(struct socket *, int); int solisten_dequeue(struct socket *, struct socket **, int); struct socket * solisten_clone(struct socket *);