215
215
nochpoll, /* c poll */
216
216
ddi_prop_op, /* property ops */
217
217
&g_VBoxNetFltSolarisStreamTab,
218
D_NEW | D_MP | D_MTQPAIR, /* compat. flag */
218
D_NEW | D_MP | D_MTQPAIR | D_MTOUTPERIM | D_MTOCEXCL, /* compat. flag */
219
219
CB_REV /* revision */
343
343
PRTTIMER pIp6Timer; /* ipv6 stream poll timer for dynamic ipv6 stream attachment */
345
345
size_t cLoopback; /* loopback queue size list */
346
timeout_id_t TimeoutId; /* timeout id of promisc. req */
346
timeout_id_t volatile TimeoutId; /* timeout id of promisc. req */
347
347
PVBOXNETFLTPACKETID pHead; /* loopback packet identifier head */
348
348
PVBOXNETFLTPACKETID pTail; /* loopback packet identifier tail */
349
349
} vboxnetflt_promisc_stream_t;
897
897
if (pStream->Type == kPromiscStream)
900
* If there are any timeout scheduled, we need to make sure they are cancelled.
902
vboxnetflt_promisc_stream_t *pPromiscStream = (vboxnetflt_promisc_stream_t *)pStream;
903
timeout_id_t TimeoutId = ASMAtomicReadPtr(&pPromiscStream->TimeoutId);
906
quntimeout(WR(pPromiscStream->Stream.pReadQueue), TimeoutId);
907
ASMAtomicWritePtr(&pPromiscStream->TimeoutId, NULL);
899
910
flushq(pQueue, FLUSHALL);
900
911
flushq(WR(pQueue), FLUSHALL);
1301
* Send fake promiscous mode requests downstream.
1312
* Callback function for qwriter to send promiscuous request messages
1303
* @param pQueue Pointer to the read queue.
1304
* @param fPromisc Whether to enable promiscous mode or not.
1305
* @param PromiscLevel Promiscous level; DL_PROMISC_PHYS/SAP/MULTI.
1315
* @param pQueue Pointer to the write queue.
1316
* @param fPromisc Whether to send promiscuous ON or OFF requests.
1307
1318
* @returns VBox status code.
1345
1356
((dl_promiscoff_req_t *)pPromiscSapMsg->b_rptr)->dl_level = DL_PROMISC_SAP;
1348
qreply(pQueue, pPromiscPhysMsg);
1349
qreply(pQueue, pPromiscSapMsg);
1359
putnext(pQueue, pPromiscPhysMsg);
1360
putnext(pQueue, pPromiscSapMsg);
1351
1362
return VINF_SUCCESS;
1356
* Callback wrapper for qtimeout to safely send promiscuous off request.
1358
* @param pvData Pointer to a vboxnetflt_promisc_params_t structure, will be freed by us.
1367
* Callback wrapper for qwriter() to safely send promiscuous requests. This is
1368
* called at the outer perimeter with exclusive lock held.
1370
* @param pQueue Pointer to the write queue.
1371
* @param pMsg A one byte message indicates a Promisc ON, otherwise
1372
* a promiscuous OFF request. See
1373
* vboxNetFltSolarisPromiscReqWrap().
1375
static void vboxNetFltSolarisPromiscReqWrapExcl(queue_t *pQueue, mblk_t *pMsg)
1380
AssertReturnVoid(pQueue);
1381
if (RT_UNLIKELY(!pMsg))
1382
LogRel((DEVICE_NAME ":VBoxNetFltSolarisPromiscReqWrapExcl pQueue=%p missing message!\n", pQueue));
1384
bool fPromisc = (MBLKL(pMsg) == 1);
1387
int rc = vboxNetFltSolarisPromiscReq(pQueue, fPromisc);
1389
LogRel((DEVICE_NAME ":VBoxNetFltSolarisPromiscReqWrapExcl vboxNetFltSolarisPromiscReq failed. rc=%d\n", rc));
1394
* Callback wrapper for qtimeout() to safely send promiscuous requests. This is
1395
* called at the inner perimenter with shared lock.
1397
* @param pvData Pointer to vboxnetflt_promisc_params_t. See
1398
* vboxNetFltPortOsSetActive().
1360
1400
static void vboxNetFltSolarisPromiscReqWrap(void *pvData)
1367
1407
if ( pPromiscStream
1368
1408
&& pPromiscStream->Stream.pReadQueue)
1370
pPromiscStream->TimeoutId = 0;
1371
vboxNetFltSolarisPromiscReq(pPromiscStream->Stream.pReadQueue, pParams->fPromiscOn);
1411
* Use size of message to indicate to qwriter callback whether it must send
1412
* promiscuous On or Off messages. This is ugly but easier and more efficient than
1413
* scheduling two separate qwriter callbacks with prepared messages to putnext.
1415
size_t cbMsg = pParams->fPromiscOn ? 1 : 2;
1416
mblk_t *pMsg = allocb(cbMsg, BPRI_HI);
1417
if (RT_UNLIKELY(!pMsg))
1419
LogRel((DEVICE_NAME ":Failed to alloc message of %u bytes\n", cbMsg));
1424
* Move the data pointer so we can use MBLKL, as MBLKSIZE gets the db_lim which is
1427
pMsg->b_wptr += cbMsg;
1430
* Upgrade inner perimeter lock to exclusive outer perimeter lock and
1431
* then call putnext while we are at the outer perimeter.
1433
qwriter(WR(pPromiscStream->Stream.pReadQueue), pMsg, vboxNetFltSolarisPromiscReqWrapExcl, PERIM_OUTER);
1434
ASMAtomicWritePtr(&pPromiscStream->TimeoutId, NULL);
1373
1436
RTMemFree(pParams);
2022
2085
if (pThis->u.s.hIface)
2025
* If there are any timeout scheduled, we need to make sure they are cancelled.
2027
vboxnetflt_promisc_stream_t *pPromiscStream = ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pvPromiscStream);
2029
&& pPromiscStream->TimeoutId)
2031
quntimeout(WR(pPromiscStream->Stream.pReadQueue), pPromiscStream->TimeoutId);
2034
2087
ldi_close(pThis->u.s.hIface, FREAD | FWRITE, kcred);
2035
2088
pThis->u.s.hIface = NULL;
3622
3675
vboxnetflt_promisc_params_t *pData = RTMemAllocZ(sizeof(vboxnetflt_promisc_params_t));
3623
3676
if (RT_LIKELY(pData))
3679
* See #5262 as to why we need to do all this qtimeout/qwriter tricks.
3625
3681
vboxnetflt_promisc_stream_t *pPromiscStream = ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pvPromiscStream);
3626
3682
if ( pPromiscStream
3627
3683
&& pPromiscStream->Stream.pReadQueue)
3629
3685
pData->pThis = pThis;
3630
3686
pData->fPromiscOn = fActive;
3631
if (pPromiscStream->TimeoutId != 0)
3687
if (ASMAtomicReadPtr(&pPromiscStream->TimeoutId))
3632
3688
quntimeout(WR(pPromiscStream->Stream.pReadQueue), pPromiscStream->TimeoutId);
3633
pPromiscStream->TimeoutId = qtimeout(WR(pPromiscStream->Stream.pReadQueue), vboxNetFltSolarisPromiscReqWrap, pData, 1 /* ticks */);
3689
timeout_id_t TimeoutId = qtimeout(WR(pPromiscStream->Stream.pReadQueue), vboxNetFltSolarisPromiscReqWrap, pData, 1 /* ticks */);
3690
ASMAtomicWritePtr(&pPromiscStream->TimeoutId, TimeoutId);
3691
return; /* pData will be freed by vboxNetFltSolarisPromiscReqWrap() */
3694
LogRel((DEVICE_NAME ":vboxNetFltPortOsSetActive pThis=%p fActive=%d missing stream!\n", pThis, fActive));
3636
3695
RTMemFree(pData);