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) { }