Print this page
More stats to SIOCIPFCFWCFG and add SIOCIPFCFWNEWSZ to affect ring-buffer size.
*** 95,112 ****
* but for now keep the ring buffer simple and stupid.
*/
/* Must be a power of 2, to be bitmaskable, and must be countable by a uint_t */
! #define IPF_CFW_RING_BUFS 1024
! #define IPF_CFW_RING_MASK (IPF_CFW_RING_BUFS - 1)
/* Assume C's init-to-zero is sufficient for these types... */
static kmutex_t cfw_ringlock;
static kcondvar_t cfw_ringcv;
! static cfwev_t cfw_evring[IPF_CFW_RING_BUFS];
/* If these are equal, we're either empty or full. */
static uint_t cfw_ringstart, cfw_ringend;
static boolean_t cfw_ringfull; /* Tell the difference here! */
static uint64_t cfw_evreports;
static uint64_t cfw_evdrops;
--- 95,116 ----
* but for now keep the ring buffer simple and stupid.
*/
/* Must be a power of 2, to be bitmaskable, and must be countable by a uint_t */
! #define IPF_CFW_DEFAULT_RING_BUFS 1024
! #define IPF_CFW_MIN_RING_BUFS 8
! #define IPF_CFW_MAX_RING_BUFS (1U << 31U)
/* Assume C's init-to-zero is sufficient for these types... */
static kmutex_t cfw_ringlock;
static kcondvar_t cfw_ringcv;
! static cfwev_t *cfw_ring; /* NULL by default. */
! static uint32_t cfw_ringsize; /* 0 by default, number of array elements. */
! static uint32_t cfw_ringmask; /* 0 by default. */
!
/* If these are equal, we're either empty or full. */
static uint_t cfw_ringstart, cfw_ringend;
static boolean_t cfw_ringfull; /* Tell the difference here! */
static uint64_t cfw_evreports;
static uint64_t cfw_evdrops;
*** 121,140 ****
ipf_cfwev_report(cfwev_t *event)
{
mutex_enter(&cfw_ringlock);
if (cfw_ringfull) {
cfw_ringstart++;
! cfw_ringstart &= IPF_CFW_RING_MASK;
cfw_ringend++;
! cfw_ringend &= IPF_CFW_RING_MASK;
DTRACE_PROBE(ipf__cfw__evdrop);
cfw_evdrops++;
! cfw_evring[cfw_ringend] = *event;
} else {
! cfw_evring[cfw_ringend] = *event;
cfw_ringend++;
! cfw_ringend &= IPF_CFW_RING_MASK;
cfw_ringfull = (cfw_ringend == cfw_ringstart);
}
cfw_evreports++;
cv_broadcast(&cfw_ringcv);
mutex_exit(&cfw_ringlock);
--- 125,144 ----
ipf_cfwev_report(cfwev_t *event)
{
mutex_enter(&cfw_ringlock);
if (cfw_ringfull) {
cfw_ringstart++;
! cfw_ringstart &= cfw_ringmask;
cfw_ringend++;
! cfw_ringend &= cfw_ringmask;
DTRACE_PROBE(ipf__cfw__evdrop);
cfw_evdrops++;
! cfw_ring[cfw_ringend] = *event;
} else {
! cfw_ring[cfw_ringend] = *event;
cfw_ringend++;
! cfw_ringend &= cfw_ringmask;
cfw_ringfull = (cfw_ringend == cfw_ringstart);
}
cfw_evreports++;
cv_broadcast(&cfw_ringcv);
mutex_exit(&cfw_ringlock);
*** 162,172 ****
mutex_exit(&cfw_ringlock);
return (B_FALSE);
}
}
! *event = cfw_evring[cfw_ringstart];
cfw_ringstart++;
cfw_ringstart &= IPF_CFW_RING_MASK;
cfw_ringfull = B_FALSE;
mutex_exit(&cfw_ringlock);
return (B_TRUE);
--- 166,176 ----
mutex_exit(&cfw_ringlock);
return (B_FALSE);
}
}
! *event = cfw_ring[cfw_ringstart];
cfw_ringstart++;
cfw_ringstart &= IPF_CFW_RING_MASK;
cfw_ringfull = B_FALSE;
mutex_exit(&cfw_ringlock);
return (B_TRUE);
*** 212,232 ****
int timeout_tries = cfw_timeout_tries;
mutex_enter(&cfw_ringlock);
/* Silly reality checks */
! ASSERT3U(cfw_ringstart, <, IPF_CFW_RING_BUFS);
! ASSERT3U(cfw_ringend, <, IPF_CFW_RING_BUFS);
/*
* Can goto here again if caller wants blocking. NOTE that
* num_requested may have been decremented and consumed may have been
* incremented if we arrive here via a goto after a cv_wait.
*/
from_the_top:
if (cfw_ringstart > cfw_ringend || cfw_ringfull)
! contig_size = IPF_CFW_RING_BUFS - cfw_ringstart;
else if (cfw_ringstart < cfw_ringend)
contig_size = cfw_ringend - cfw_ringstart;
else if (block && cv_wait_sig(&cfw_ringcv, &cfw_ringlock)) {
/* Maybe something to consume now, try again. */
goto from_the_top;
--- 216,236 ----
int timeout_tries = cfw_timeout_tries;
mutex_enter(&cfw_ringlock);
/* Silly reality checks */
! ASSERT3U(cfw_ringstart, <, cfw_ringsize);
! ASSERT3U(cfw_ringend, <, cfw_ringsize);
/*
* Can goto here again if caller wants blocking. NOTE that
* num_requested may have been decremented and consumed may have been
* incremented if we arrive here via a goto after a cv_wait.
*/
from_the_top:
if (cfw_ringstart > cfw_ringend || cfw_ringfull)
! contig_size = cfw_ringsize - cfw_ringstart;
else if (cfw_ringstart < cfw_ringend)
contig_size = cfw_ringend - cfw_ringstart;
else if (block && cv_wait_sig(&cfw_ringcv, &cfw_ringlock)) {
/* Maybe something to consume now, try again. */
goto from_the_top;
*** 234,271 ****
/* Nothing (more) to consume, return! */
goto bail;
}
ASSERT(contig_size + cfw_ringstart == cfw_ringend ||
! contig_size + cfw_ringstart == IPF_CFW_RING_BUFS);
if (num_requested < contig_size)
contig_size = num_requested;
! cb_consumed = cfw_many_cb(&(cfw_evring[cfw_ringstart]), contig_size,
cbarg);
ASSERT(cb_consumed <= contig_size);
cfw_ringstart += cb_consumed;
consumed += cb_consumed;
cfw_ringfull = (cfw_ringfull && cb_consumed == 0);
if (cb_consumed < contig_size) {
/* Caller clearly had a problem. Reality check and bail. */
! ASSERT((cfw_ringstart & IPF_CFW_RING_MASK) == cfw_ringstart);
goto bail;
}
ASSERT(cb_consumed == contig_size);
! cfw_ringstart &= IPF_CFW_RING_MASK; /* In case of wraparound. */
num_requested -= contig_size;
if (num_requested > 0 && cfw_ringstart != cfw_ringend) {
/* We must have wrapped around the end of the buffer! */
ASSERT(cfw_ringstart == 0);
ASSERT(!cfw_ringfull);
contig_size = cfw_ringend;
if (num_requested < contig_size)
contig_size = num_requested;
! cb_consumed = cfw_many_cb(&(cfw_evring[cfw_ringstart]),
contig_size, cbarg);
cfw_ringstart += cb_consumed;
consumed += cb_consumed;
if (cb_consumed < contig_size) {
/*
--- 238,275 ----
/* Nothing (more) to consume, return! */
goto bail;
}
ASSERT(contig_size + cfw_ringstart == cfw_ringend ||
! contig_size + cfw_ringstart == cfw_ringsize);
if (num_requested < contig_size)
contig_size = num_requested;
! cb_consumed = cfw_many_cb(&(cfw_ring[cfw_ringstart]), contig_size,
cbarg);
ASSERT(cb_consumed <= contig_size);
cfw_ringstart += cb_consumed;
consumed += cb_consumed;
cfw_ringfull = (cfw_ringfull && cb_consumed == 0);
if (cb_consumed < contig_size) {
/* Caller clearly had a problem. Reality check and bail. */
! ASSERT((cfw_ringstart & cfw_ringmask) == cfw_ringstart);
goto bail;
}
ASSERT(cb_consumed == contig_size);
! cfw_ringstart &= cfw_ringmask; /* In case of wraparound. */
num_requested -= contig_size;
if (num_requested > 0 && cfw_ringstart != cfw_ringend) {
/* We must have wrapped around the end of the buffer! */
ASSERT(cfw_ringstart == 0);
ASSERT(!cfw_ringfull);
contig_size = cfw_ringend;
if (num_requested < contig_size)
contig_size = num_requested;
! cb_consumed = cfw_many_cb(&(cfw_ring[cfw_ringstart]),
contig_size, cbarg);
cfw_ringstart += cb_consumed;
consumed += cb_consumed;
if (cb_consumed < contig_size) {
/*
*** 497,530 ****
return (0);
return (num_avail);
}
/* ARGSUSED */
int
ipf_cfwlog_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *cp,
int *rp)
{
ipfcfwcfg_t cfginfo;
int error;
! if (cmd != SIOCIPFCFWCFG)
return (EIO);
if (crgetzoneid(cp) != GLOBAL_ZONEID)
return (EACCES);
- #ifdef notyet
error = COPYIN((caddr_t)data, (caddr_t)&cfginfo, sizeof (cfginfo));
if (error != 0)
return (EFAULT);
- /* TODO: Resize ring buffer based on cfginfo.ipfcfwc_evringsize. */
- #endif
cfginfo.ipfcfwc_maxevsize = sizeof (cfwev_t);
! cfginfo.ipfcfwc_evringsize = IPF_CFW_RING_BUFS;
error = COPYOUT((caddr_t)&cfginfo, (caddr_t)data, sizeof (cfginfo));
if (error != 0)
return (EFAULT);
return (0);
--- 501,596 ----
return (0);
return (num_avail);
}
+ int
+ ipf_cfw_ring_resize(uint32_t newsize)
+ {
+ ASSERT(MUTEX_HELD(&cfw_ringlock) || newsize == IPF_CFW_RING_ALLOCATE ||
+ newsize == IPF_CFW_RING_DESTROY);
+
+ if (newsize == IPF_CFW_RING_ALLOCATE) {
+ if (cfw_ring != NULL)
+ return (EBUSY);
+ newsize = IPF_CFW_DEFAULT_RING_BUFS;
+ /* Fall through to allocating a new ring buffer. */
+ } else {
+ /* We may be called during error cleanup, so be liberal here. */
+ if (cfw_ring == NULL && newsize == IPF_CFW_RING_DESTROY)
+ return (0);
+ kmem_free(cfw_ring, cfw_ringsize * sizeof (cfwev_t));
+ cfw_ring = NULL;
+ if (cfw_ringfull) {
+ cfw_evdrops += cfw_ringsize;
+ } else if (cfw_ringstart > cfw_ringend) {
+ cfw_evdrops += cfw_ringend +
+ (cfw_ringsize - cfw_ringstart);
+ } else {
+ cfw_evdrops += cfw_ringend - cfw_ringstart;
+ }
+ cfw_ringsize = cfw_ringmask = cfw_ringstart = cfw_ringend = 0;
+ cfw_ringfull = B_FALSE;
+
+ if (newsize == IPF_CFW_RING_DESTROY)
+ return (0);
+ /*
+ * Keep the reports & drops around because if we're just
+ * resizing, we need to know what we lost.
+ */
+ }
+
+ ASSERT(ISP2(newsize));
+ cfw_ring = kmem_alloc(newsize * sizeof (cfwev_t), KM_SLEEP);
+ /* KM_SLEEP means we always succeed. */
+ cfw_ringsize = newsize;
+ cfw_ringmask = cfw_ringsize - 1;
+
+ return (0);
+ }
+
/* ARGSUSED */
int
ipf_cfwlog_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *cp,
int *rp)
{
ipfcfwcfg_t cfginfo;
int error;
! if (cmd != SIOCIPFCFWCFG && cmd != SIOCIPFCFWNEWSZ)
return (EIO);
if (crgetzoneid(cp) != GLOBAL_ZONEID)
return (EACCES);
error = COPYIN((caddr_t)data, (caddr_t)&cfginfo, sizeof (cfginfo));
if (error != 0)
return (EFAULT);
cfginfo.ipfcfwc_maxevsize = sizeof (cfwev_t);
! mutex_enter(&cfw_ringlock);
! cfginfo.ipfcfwc_evreports = cfw_evreports;
! cfginfo.ipfcfwc_evdrops = cfw_evdrops;
! if (cmd == SIOCIPFCFWNEWSZ) {
! uint32_t newsize = cfginfo.ipfcfwc_evringsize;
+ /* Do ioctl parameter checking here, then call the resizer. */
+ if (newsize < IPF_CFW_MIN_RING_BUFS ||
+ newsize > IPF_CFW_MAX_RING_BUFS || !ISP2(newsize)) {
+ error = EINVAL;
+ } else {
+ error = ipf_cfw_ring_resize(cfginfo.ipfcfwc_evringsize);
+ }
+ } else {
+ error = 0;
+ }
+ cfginfo.ipfcfwc_evringsize = cfw_ringsize;
+ mutex_exit(&cfw_ringlock);
+
+ if (error != 0)
+ return (error);
+
error = COPYOUT((caddr_t)&cfginfo, (caddr_t)data, sizeof (cfginfo));
if (error != 0)
return (EFAULT);
return (0);
*** 575,584 ****
--- 641,656 ----
#else
/* Blank stubs to satisfy userland's test compilations. */
+ int
+ ipf_cfw_ring_resize(uint32_t a)
+ {
+ return (0);
+ }
+
void
ipf_log_cfwlog(struct ipstate *a, uint_t b, ipf_stack_t *c)
{
}