Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/uipc_socket.c
Show First 20 Lines • Show All 565 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
#ifdef REGRESSION | #ifdef REGRESSION | ||||
static int regression_sonewconn_earlytest = 1; | static int regression_sonewconn_earlytest = 1; | ||||
SYSCTL_INT(_regression, OID_AUTO, sonewconn_earlytest, CTLFLAG_RW, | SYSCTL_INT(_regression, OID_AUTO, sonewconn_earlytest, CTLFLAG_RW, | ||||
®ression_sonewconn_earlytest, 0, "Perform early sonewconn limit test"); | ®ression_sonewconn_earlytest, 0, "Perform early sonewconn limit test"); | ||||
#endif | #endif | ||||
static timeval overinterval = { 60, 0 }; | |||||
SYSCTL_TIMEVAL_SEC(_kern_ipc, OID_AUTO, sooverinterval, CTLFLAG_RW, | |||||
&overinterval, | |||||
"Delay in seconds between warnings for listen socket overflows"); | |||||
/* | /* | ||||
* When an attempt at a new connection is noted on a socket which accepts | * When an attempt at a new connection is noted on a socket which accepts | ||||
* connections, sonewconn is called. If the connection is possible (subject | * connections, sonewconn is called. If the connection is possible (subject | ||||
* to space constraints, etc.) then we allocate a new structure, properly | * to space constraints, etc.) then we allocate a new structure, properly | ||||
* linked into the data structure of the original socket, and return this. | * linked into the data structure of the original socket, and return this. | ||||
* Connstatus may be 0, or SS_ISCONFIRMING, or SS_ISCONNECTED. | * Connstatus may be 0, or SS_ISCONFIRMING, or SS_ISCONNECTED. | ||||
* | * | ||||
* Note: the ref count on the socket is 0 on return. | * Note: the ref count on the socket is 0 on return. | ||||
*/ | */ | ||||
struct socket * | struct socket * | ||||
sonewconn(struct socket *head, int connstatus) | sonewconn(struct socket *head, int connstatus) | ||||
{ | { | ||||
static struct timeval lastover; | |||||
static struct timeval overinterval = { 60, 0 }; | |||||
static int overcount; | |||||
struct socket *so; | struct socket *so; | ||||
jhb: BTW, you could consider making this a sysctl. I added a `SYSCTL_TIMEVAL` for the various… | |||||
Done Inline ActionsThanks! I implemented this suggestion. jtl: Thanks! I implemented this suggestion. | |||||
u_int over; | int overcount; | ||||
u_int qlen; | |||||
bool dolog, over; | |||||
SOLISTEN_LOCK(head); | SOLISTEN_LOCK(head); | ||||
over = (head->sol_qlen > 3 * head->sol_qlimit / 2); | over = (head->sol_qlen > 3 * head->sol_qlimit / 2); | ||||
SOLISTEN_UNLOCK(head); | |||||
#ifdef REGRESSION | #ifdef REGRESSION | ||||
if (regression_sonewconn_earlytest && over) { | if (regression_sonewconn_earlytest && over) { | ||||
#else | #else | ||||
if (over) { | if (over) { | ||||
#endif | #endif | ||||
overcount++; | head->sol_overcount++; | ||||
dolog = !!ratecheck(&head->sol_lastover, &overinterval); | |||||
if (ratecheck(&lastover, &overinterval)) { | /* | ||||
* If we're going to log, copy the overflow count and queue | |||||
* length from the listen socket before dropping the lock. | |||||
* Also, reset the overflow count. | |||||
*/ | |||||
if (dolog) { | |||||
overcount = head->sol_overcount; | |||||
head->sol_overcount = 0; | |||||
qlen = head->sol_qlen; | |||||
} | |||||
SOLISTEN_UNLOCK(head); | |||||
if (dolog) { | |||||
log(LOG_DEBUG, "%s: pcb %p: Listen queue overflow: " | log(LOG_DEBUG, "%s: pcb %p: Listen queue overflow: " | ||||
"%i already in queue awaiting acceptance " | "%i already in queue awaiting acceptance " | ||||
"(%d occurrences)\n", | "(%d occurrences)\n", | ||||
__func__, head->so_pcb, head->sol_qlen, overcount); | __func__, head->so_pcb, qlen, overcount); | ||||
overcount = 0; | |||||
} | } | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
SOLISTEN_UNLOCK(head); | |||||
VNET_ASSERT(head->so_vnet != NULL, ("%s: so %p vnet is NULL", | VNET_ASSERT(head->so_vnet != NULL, ("%s: so %p vnet is NULL", | ||||
__func__, head)); | __func__, head)); | ||||
so = soalloc(head->so_vnet); | so = soalloc(head->so_vnet); | ||||
if (so == NULL) { | if (so == NULL) { | ||||
log(LOG_DEBUG, "%s: pcb %p: New socket allocation failure: " | log(LOG_DEBUG, "%s: pcb %p: New socket allocation failure: " | ||||
"limit reached or out of memory\n", | "limit reached or out of memory\n", | ||||
__func__, head->so_pcb); | __func__, head->so_pcb); | ||||
return (NULL); | return (NULL); | ||||
▲ Show 20 Lines • Show All 3,630 Lines • Show Last 20 Lines |
BTW, you could consider making this a sysctl. I added a SYSCTL_TIMEVAL for the various crypto deprecation warnings that exposes the seconds portion as an integer value.