summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/inet/squeue.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/inet/squeue.c')
-rw-r--r--usr/src/uts/common/inet/squeue.c112
1 files changed, 100 insertions, 12 deletions
diff --git a/usr/src/uts/common/inet/squeue.c b/usr/src/uts/common/inet/squeue.c
index e46293d820..db11ef79ae 100644
--- a/usr/src/uts/common/inet/squeue.c
+++ b/usr/src/uts/common/inet/squeue.c
@@ -39,8 +39,8 @@
* parallelization (on a per H/W execution pipeline basis) with at
* most one queuing.
*
- * The modules needing protection typically calls squeue_enter() or
- * squeue_enter_chain() routine as soon as a thread enter the module
+ * The modules needing protection typically calls SQUEUE_ENTER_ONE() or
+ * SQUEUE_ENTER() macro as soon as a thread enter the module
* from either direction. For each packet, the processing function
* and argument is stored in the mblk itself. When the packet is ready
* to be processed, the squeue retrieves the stored function and calls
@@ -406,11 +406,15 @@ squeue_worker_wakeup(squeue_t *sqp)
* and drain in the entering thread context. If process_flag is
* SQ_FILL, then we just queue the mblk and return (after signaling
* the worker thread if no one else is processing the squeue).
+ *
+ * The ira argument can be used when the count is one.
+ * For a chain the caller needs to prepend any needed mblks from
+ * ip_recv_attr_to_mblk().
*/
/* ARGSUSED */
void
squeue_enter(squeue_t *sqp, mblk_t *mp, mblk_t *tail, uint32_t cnt,
- int process_flag, uint8_t tag)
+ ip_recv_attr_t *ira, int process_flag, uint8_t tag)
{
conn_t *connp;
sqproc_t proc;
@@ -421,6 +425,7 @@ squeue_enter(squeue_t *sqp, mblk_t *mp, mblk_t *tail, uint32_t cnt,
ASSERT(tail != NULL);
ASSERT(cnt > 0);
ASSERT(MUTEX_NOT_HELD(&sqp->sq_lock));
+ ASSERT(ira == NULL || cnt == 1);
mutex_enter(&sqp->sq_lock);
@@ -467,7 +472,7 @@ squeue_enter(squeue_t *sqp, mblk_t *mp, mblk_t *tail, uint32_t cnt,
connp->conn_on_sqp = B_TRUE;
DTRACE_PROBE3(squeue__proc__start, squeue_t *,
sqp, mblk_t *, mp, conn_t *, connp);
- (*proc)(connp, mp, sqp);
+ (*proc)(connp, mp, sqp, ira);
DTRACE_PROBE2(squeue__proc__end, squeue_t *,
sqp, conn_t *, connp);
connp->conn_on_sqp = B_FALSE;
@@ -475,7 +480,7 @@ squeue_enter(squeue_t *sqp, mblk_t *mp, mblk_t *tail, uint32_t cnt,
CONN_DEC_REF(connp);
} else {
SQUEUE_ENTER_ONE(connp->conn_sqp, mp, proc,
- connp, SQ_FILL, SQTAG_SQUEUE_CHANGE);
+ connp, ira, SQ_FILL, SQTAG_SQUEUE_CHANGE);
}
ASSERT(MUTEX_NOT_HELD(&sqp->sq_lock));
mutex_enter(&sqp->sq_lock);
@@ -499,6 +504,33 @@ squeue_enter(squeue_t *sqp, mblk_t *mp, mblk_t *tail, uint32_t cnt,
return;
}
} else {
+ if (ira != NULL) {
+ mblk_t *attrmp;
+
+ ASSERT(cnt == 1);
+ attrmp = ip_recv_attr_to_mblk(ira);
+ if (attrmp == NULL) {
+ mutex_exit(&sqp->sq_lock);
+ ip_drop_input("squeue: "
+ "ip_recv_attr_to_mblk",
+ mp, NULL);
+ /* Caller already set b_prev/b_next */
+ mp->b_prev = mp->b_next = NULL;
+ freemsg(mp);
+ return;
+ }
+ ASSERT(attrmp->b_cont == NULL);
+ attrmp->b_cont = mp;
+ /* Move connp and func to new */
+ attrmp->b_queue = mp->b_queue;
+ mp->b_queue = NULL;
+ attrmp->b_prev = mp->b_prev;
+ mp->b_prev = NULL;
+
+ ASSERT(mp == tail);
+ tail = mp = attrmp;
+ }
+
ENQUEUE_CHAIN(sqp, mp, tail, cnt);
#ifdef DEBUG
mp->b_tag = tag;
@@ -564,14 +596,14 @@ squeue_enter(squeue_t *sqp, mblk_t *mp, mblk_t *tail, uint32_t cnt,
connp->conn_on_sqp = B_TRUE;
DTRACE_PROBE3(squeue__proc__start, squeue_t *,
sqp, mblk_t *, mp, conn_t *, connp);
- (*proc)(connp, mp, sqp);
+ (*proc)(connp, mp, sqp, ira);
DTRACE_PROBE2(squeue__proc__end, squeue_t *,
sqp, conn_t *, connp);
connp->conn_on_sqp = B_FALSE;
CONN_DEC_REF(connp);
} else {
SQUEUE_ENTER_ONE(connp->conn_sqp, mp, proc,
- connp, SQ_FILL, SQTAG_SQUEUE_CHANGE);
+ connp, ira, SQ_FILL, SQTAG_SQUEUE_CHANGE);
}
mutex_enter(&sqp->sq_lock);
@@ -589,7 +621,31 @@ squeue_enter(squeue_t *sqp, mblk_t *mp, mblk_t *tail, uint32_t cnt,
#ifdef DEBUG
mp->b_tag = tag;
#endif
+ if (ira != NULL) {
+ mblk_t *attrmp;
+ ASSERT(cnt == 1);
+ attrmp = ip_recv_attr_to_mblk(ira);
+ if (attrmp == NULL) {
+ mutex_exit(&sqp->sq_lock);
+ ip_drop_input("squeue: ip_recv_attr_to_mblk",
+ mp, NULL);
+ /* Caller already set b_prev/b_next */
+ mp->b_prev = mp->b_next = NULL;
+ freemsg(mp);
+ return;
+ }
+ ASSERT(attrmp->b_cont == NULL);
+ attrmp->b_cont = mp;
+ /* Move connp and func to new */
+ attrmp->b_queue = mp->b_queue;
+ mp->b_queue = NULL;
+ attrmp->b_prev = mp->b_prev;
+ mp->b_prev = NULL;
+
+ ASSERT(mp == tail);
+ tail = mp = attrmp;
+ }
ENQUEUE_CHAIN(sqp, mp, tail, cnt);
if (!(sqp->sq_state & SQS_PROC)) {
squeue_worker_wakeup(sqp);
@@ -653,6 +709,7 @@ squeue_drain(squeue_t *sqp, uint_t proc_type, hrtime_t expire)
hrtime_t now;
boolean_t did_wakeup = B_FALSE;
boolean_t sq_poll_capable;
+ ip_recv_attr_t *ira, iras;
sq_poll_capable = (sqp->sq_state & SQS_POLL_CAPAB) != 0;
again:
@@ -697,6 +754,31 @@ again:
connp = (conn_t *)mp->b_prev;
mp->b_prev = NULL;
+ /* Is there an ip_recv_attr_t to handle? */
+ if (ip_recv_attr_is_mblk(mp)) {
+ mblk_t *attrmp = mp;
+
+ ASSERT(attrmp->b_cont != NULL);
+
+ mp = attrmp->b_cont;
+ attrmp->b_cont = NULL;
+ ASSERT(mp->b_queue == NULL);
+ ASSERT(mp->b_prev == NULL);
+
+ if (!ip_recv_attr_from_mblk(attrmp, &iras)) {
+ /* The ill or ip_stack_t disappeared on us */
+ ip_drop_input("ip_recv_attr_from_mblk",
+ mp, NULL);
+ ira_cleanup(&iras, B_TRUE);
+ CONN_DEC_REF(connp);
+ continue;
+ }
+ ira = &iras;
+ } else {
+ ira = NULL;
+ }
+
+
/*
* Handle squeue switching. More details in the
* block comment at the top of the file
@@ -707,15 +789,17 @@ again:
connp->conn_on_sqp = B_TRUE;
DTRACE_PROBE3(squeue__proc__start, squeue_t *,
sqp, mblk_t *, mp, conn_t *, connp);
- (*proc)(connp, mp, sqp);
+ (*proc)(connp, mp, sqp, ira);
DTRACE_PROBE2(squeue__proc__end, squeue_t *,
sqp, conn_t *, connp);
connp->conn_on_sqp = B_FALSE;
CONN_DEC_REF(connp);
} else {
- SQUEUE_ENTER_ONE(connp->conn_sqp, mp, proc, connp,
+ SQUEUE_ENTER_ONE(connp->conn_sqp, mp, proc, connp, ira,
SQ_FILL, SQTAG_SQUEUE_CHANGE);
}
+ if (ira != NULL)
+ ira_cleanup(ira, B_TRUE);
}
SQUEUE_DBG_CLEAR(sqp);
@@ -991,9 +1075,13 @@ poll_again:
&tail, &cnt);
}
mutex_enter(lock);
- if (mp != NULL)
+ if (mp != NULL) {
+ /*
+ * The ip_accept function has already added an
+ * ip_recv_attr_t mblk if that is needed.
+ */
ENQUEUE_CHAIN(sqp, mp, tail, cnt);
-
+ }
ASSERT((sqp->sq_state &
(SQS_PROC|SQS_POLLING|SQS_GET_PKTS)) ==
(SQS_PROC|SQS_POLLING|SQS_GET_PKTS));
@@ -1263,7 +1351,7 @@ squeue_getprivate(squeue_t *sqp, sqprivate_t p)
/* ARGSUSED */
void
-squeue_wakeup_conn(void *arg, mblk_t *mp, void *arg2)
+squeue_wakeup_conn(void *arg, mblk_t *mp, void *arg2, ip_recv_attr_t *dummy)
{
conn_t *connp = (conn_t *)arg;
squeue_t *sqp = connp->conn_sqp;