Print this page
More stats to SIOCIPFCFWCFG and add SIOCIPFCFWNEWSZ to affect ring-buffer size.

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/inet/ipf/cfw.c
          +++ new/usr/src/uts/common/inet/ipf/cfw.c
↓ open down ↓ 89 lines elided ↑ open up ↑
  90   90   * not something to instantiate per-netstack.
  91   91   */
  92   92  
  93   93  /*
  94   94   * We may want to get more sophisticated and performant (e.g. per-processor),
  95   95   * but for now keep the ring buffer simple and stupid.
  96   96   */
  97   97  
  98   98  /* Must be a power of 2, to be bitmaskable, and must be countable by a uint_t */
  99   99  
 100      -#define IPF_CFW_RING_BUFS       1024
 101      -#define IPF_CFW_RING_MASK (IPF_CFW_RING_BUFS - 1)
      100 +#define IPF_CFW_DEFAULT_RING_BUFS       1024
      101 +#define IPF_CFW_MIN_RING_BUFS           8
      102 +#define IPF_CFW_MAX_RING_BUFS           (1U << 31U)
 102  103  
 103  104  /* Assume C's init-to-zero is sufficient for these types... */
 104  105  static kmutex_t cfw_ringlock;
 105  106  static kcondvar_t cfw_ringcv;
 106  107  
 107      -static cfwev_t cfw_evring[IPF_CFW_RING_BUFS];
      108 +static cfwev_t *cfw_ring;       /* NULL by default. */
      109 +static uint32_t cfw_ringsize;   /* 0 by default, number of array elements. */
      110 +static uint32_t cfw_ringmask;   /* 0 by default. */
      111 +
 108  112  /* If these are equal, we're either empty or full. */
 109  113  static uint_t cfw_ringstart, cfw_ringend;
 110  114  static boolean_t cfw_ringfull;  /* Tell the difference here! */
 111  115  static uint64_t cfw_evreports;
 112  116  static uint64_t cfw_evdrops;
 113  117  
 114  118  /*
 115  119   * Place an event in the CFW event ring buffer.
 116  120   *
 117  121   * For now, be simple and drop the oldest event if we overflow. We may wish to
 118  122   * selectively drop older events based on type in the future.
 119  123   */
 120  124  static void
 121  125  ipf_cfwev_report(cfwev_t *event)
 122  126  {
 123  127          mutex_enter(&cfw_ringlock);
 124  128          if (cfw_ringfull) {
 125  129                  cfw_ringstart++;
 126      -                cfw_ringstart &= IPF_CFW_RING_MASK;
      130 +                cfw_ringstart &= cfw_ringmask;
 127  131                  cfw_ringend++;
 128      -                cfw_ringend &= IPF_CFW_RING_MASK;
      132 +                cfw_ringend &= cfw_ringmask;
 129  133                  DTRACE_PROBE(ipf__cfw__evdrop);
 130  134                  cfw_evdrops++;
 131      -                cfw_evring[cfw_ringend] = *event;
      135 +                cfw_ring[cfw_ringend] = *event;
 132  136          } else {
 133      -                cfw_evring[cfw_ringend] = *event;
      137 +                cfw_ring[cfw_ringend] = *event;
 134  138                  cfw_ringend++;
 135      -                cfw_ringend &= IPF_CFW_RING_MASK;
      139 +                cfw_ringend &= cfw_ringmask;
 136  140                  cfw_ringfull = (cfw_ringend == cfw_ringstart);
 137  141          }
 138  142          cfw_evreports++;
 139  143          cv_broadcast(&cfw_ringcv);
 140  144          mutex_exit(&cfw_ringlock);
 141  145  }
 142  146  
 143  147  #if 0
 144  148  /*
 145  149   * Simple event consumer which copies one event from the ring buffer into
↓ open down ↓ 11 lines elided ↑ open up ↑
 157  161          /*
 158  162           * Return B_FALSE if non-block and no data, OR if we receive a signal.
 159  163           */
 160  164          while ((cfw_ringstart == cfw_ringend) && !cfw_ringfull) {
 161  165                  if (!block || !cv_wait_sig(&cfw_ringcv, &cfw_ringlock)) {
 162  166                          mutex_exit(&cfw_ringlock);
 163  167                          return (B_FALSE);
 164  168                  }
 165  169          }
 166  170  
 167      -        *event = cfw_evring[cfw_ringstart];
      171 +        *event = cfw_ring[cfw_ringstart];
 168  172          cfw_ringstart++;
 169  173          cfw_ringstart &= IPF_CFW_RING_MASK;
 170  174          cfw_ringfull = B_FALSE;
 171  175          mutex_exit(&cfw_ringlock);
 172  176          return (B_TRUE);
 173  177  }
 174  178  #endif
 175  179  
 176  180  /*
 177  181   * More sophisticated access to multiple CFW events that can allow copying
↓ open down ↓ 29 lines elided ↑ open up ↑
 207  211  uint_t
 208  212  ipf_cfwev_consume_many(uint_t num_requested, boolean_t block,
 209  213      cfwmanycb_t cfw_many_cb, void *cbarg)
 210  214  {
 211  215          uint_t consumed = 0, cb_consumed, contig_size;
 212  216          int timeout_tries = cfw_timeout_tries;
 213  217  
 214  218          mutex_enter(&cfw_ringlock);
 215  219  
 216  220          /* Silly reality checks */
 217      -        ASSERT3U(cfw_ringstart, <, IPF_CFW_RING_BUFS);
 218      -        ASSERT3U(cfw_ringend, <, IPF_CFW_RING_BUFS);
      221 +        ASSERT3U(cfw_ringstart, <, cfw_ringsize);
      222 +        ASSERT3U(cfw_ringend, <, cfw_ringsize);
 219  223  
 220  224          /*
 221  225           * Can goto here again if caller wants blocking. NOTE that
 222  226           * num_requested may have been decremented and consumed may have been
 223  227           * incremented if we arrive here via a goto after a cv_wait.
 224  228           */
 225  229  from_the_top:
 226  230          if (cfw_ringstart > cfw_ringend || cfw_ringfull)
 227      -                contig_size = IPF_CFW_RING_BUFS - cfw_ringstart;
      231 +                contig_size = cfw_ringsize - cfw_ringstart;
 228  232          else if (cfw_ringstart < cfw_ringend)
 229  233                  contig_size = cfw_ringend - cfw_ringstart;
 230  234          else if (block && cv_wait_sig(&cfw_ringcv, &cfw_ringlock)) {
 231  235                  /* Maybe something to consume now, try again. */
 232  236                  goto from_the_top;
 233  237          } else {
 234  238                  /* Nothing (more) to consume, return! */
 235  239                  goto bail;
 236  240          }
 237  241  
 238  242          ASSERT(contig_size + cfw_ringstart == cfw_ringend ||
 239      -            contig_size + cfw_ringstart == IPF_CFW_RING_BUFS);
      243 +            contig_size + cfw_ringstart == cfw_ringsize);
 240  244  
 241  245          if (num_requested < contig_size)
 242  246                  contig_size = num_requested;
 243  247  
 244      -        cb_consumed = cfw_many_cb(&(cfw_evring[cfw_ringstart]), contig_size,
      248 +        cb_consumed = cfw_many_cb(&(cfw_ring[cfw_ringstart]), contig_size,
 245  249              cbarg);
 246  250          ASSERT(cb_consumed <= contig_size);
 247  251          cfw_ringstart += cb_consumed;
 248  252          consumed += cb_consumed;
 249  253          cfw_ringfull = (cfw_ringfull && cb_consumed == 0);
 250  254          if (cb_consumed < contig_size) {
 251  255                  /* Caller clearly had a problem. Reality check and bail. */
 252      -                ASSERT((cfw_ringstart & IPF_CFW_RING_MASK) == cfw_ringstart);
      256 +                ASSERT((cfw_ringstart & cfw_ringmask) == cfw_ringstart);
 253  257                  goto bail;
 254  258          }
 255  259          ASSERT(cb_consumed == contig_size);
 256      -        cfw_ringstart &= IPF_CFW_RING_MASK;     /* In case of wraparound. */
      260 +        cfw_ringstart &= cfw_ringmask;  /* In case of wraparound. */
 257  261          num_requested -= contig_size;
 258  262  
 259  263          if (num_requested > 0 && cfw_ringstart != cfw_ringend) {
 260  264                  /* We must have wrapped around the end of the buffer! */
 261  265                  ASSERT(cfw_ringstart == 0);
 262  266                  ASSERT(!cfw_ringfull);
 263  267                  contig_size = cfw_ringend;
 264  268                  if (num_requested < contig_size)
 265  269                          contig_size = num_requested;
 266      -                cb_consumed = cfw_many_cb(&(cfw_evring[cfw_ringstart]),
      270 +                cb_consumed = cfw_many_cb(&(cfw_ring[cfw_ringstart]),
 267  271                      contig_size, cbarg);
 268  272                  cfw_ringstart += cb_consumed;
 269  273                  consumed += cb_consumed;
 270  274                  if (cb_consumed < contig_size) {
 271  275                          /*
 272  276                           * Caller clearly had a problem. Reality check and
 273  277                           * bail.
 274  278                           */
 275  279                          ASSERT(cfw_ringend > cfw_ringstart);
 276  280                          goto bail;
↓ open down ↓ 215 lines elided ↑ open up ↑
 492  496                  return (0);
 493  497  
 494  498          ue->ue_error = uiomove((caddr_t)evptr, num_avail * sizeof (*evptr),
 495  499              UIO_READ, ue->ue_uio);
 496  500          if (ue->ue_error != 0)
 497  501                  return (0);
 498  502  
 499  503          return (num_avail);
 500  504  }
 501  505  
      506 +int
      507 +ipf_cfw_ring_resize(uint32_t newsize)
      508 +{
      509 +        ASSERT(MUTEX_HELD(&cfw_ringlock) || newsize == IPF_CFW_RING_ALLOCATE ||
      510 +            newsize == IPF_CFW_RING_DESTROY);
      511 +
      512 +        if (newsize == IPF_CFW_RING_ALLOCATE) {
      513 +                if (cfw_ring != NULL)
      514 +                        return (EBUSY);
      515 +                newsize = IPF_CFW_DEFAULT_RING_BUFS;
      516 +                /* Fall through to allocating a new ring buffer. */
      517 +        } else {
      518 +                /* We may be called during error cleanup, so be liberal here. */
      519 +                if (cfw_ring == NULL && newsize == IPF_CFW_RING_DESTROY)
      520 +                        return (0);
      521 +                kmem_free(cfw_ring, cfw_ringsize * sizeof (cfwev_t));
      522 +                cfw_ring = NULL;
      523 +                if (cfw_ringfull) {
      524 +                        cfw_evdrops += cfw_ringsize;
      525 +                } else if (cfw_ringstart > cfw_ringend) {
      526 +                        cfw_evdrops += cfw_ringend +
      527 +                            (cfw_ringsize - cfw_ringstart);
      528 +                } else {
      529 +                        cfw_evdrops += cfw_ringend - cfw_ringstart;
      530 +                }
      531 +                cfw_ringsize = cfw_ringmask = cfw_ringstart = cfw_ringend = 0;
      532 +                cfw_ringfull = B_FALSE;
      533 +
      534 +                if (newsize == IPF_CFW_RING_DESTROY)
      535 +                        return (0);
      536 +                /*
      537 +                 * Keep the reports & drops around because if we're just
      538 +                 * resizing, we need to know what we lost.
      539 +                 */
      540 +        }
      541 +
      542 +        ASSERT(ISP2(newsize));
      543 +        cfw_ring = kmem_alloc(newsize * sizeof (cfwev_t), KM_SLEEP);
      544 +        /* KM_SLEEP means we always succeed. */
      545 +        cfw_ringsize = newsize;
      546 +        cfw_ringmask = cfw_ringsize - 1;
      547 +
      548 +        return (0);
      549 +}
      550 +
 502  551  /* ARGSUSED */
 503  552  int
 504  553  ipf_cfwlog_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *cp,
 505  554      int *rp)
 506  555  {
 507  556          ipfcfwcfg_t cfginfo;
 508  557          int error;
 509  558  
 510      -        if (cmd != SIOCIPFCFWCFG)
      559 +        if (cmd != SIOCIPFCFWCFG && cmd != SIOCIPFCFWNEWSZ)
 511  560                  return (EIO);
 512  561  
 513  562          if (crgetzoneid(cp) != GLOBAL_ZONEID)
 514  563                  return (EACCES);
 515  564  
 516      -#ifdef notyet
 517  565          error = COPYIN((caddr_t)data, (caddr_t)&cfginfo, sizeof (cfginfo));
 518  566          if (error != 0)
 519  567                  return (EFAULT);
 520      -        /* TODO: Resize ring buffer based on cfginfo.ipfcfwc_evringsize. */
 521      -#endif
 522  568  
 523  569          cfginfo.ipfcfwc_maxevsize = sizeof (cfwev_t);
 524      -        cfginfo.ipfcfwc_evringsize = IPF_CFW_RING_BUFS;
      570 +        mutex_enter(&cfw_ringlock);
      571 +        cfginfo.ipfcfwc_evreports = cfw_evreports;
      572 +        cfginfo.ipfcfwc_evdrops = cfw_evdrops;
      573 +        if (cmd == SIOCIPFCFWNEWSZ) {
      574 +                uint32_t newsize = cfginfo.ipfcfwc_evringsize;
 525  575  
      576 +                /* Do ioctl parameter checking here, then call the resizer. */
      577 +                if (newsize < IPF_CFW_MIN_RING_BUFS ||
      578 +                    newsize > IPF_CFW_MAX_RING_BUFS || !ISP2(newsize)) {
      579 +                        error = EINVAL;
      580 +                } else {
      581 +                        error = ipf_cfw_ring_resize(cfginfo.ipfcfwc_evringsize);
      582 +                }
      583 +        } else {
      584 +                error = 0;
      585 +        }
      586 +        cfginfo.ipfcfwc_evringsize = cfw_ringsize;
      587 +        mutex_exit(&cfw_ringlock);
      588 +
      589 +        if (error != 0)
      590 +                return (error);
      591 +
 526  592          error = COPYOUT((caddr_t)&cfginfo, (caddr_t)data, sizeof (cfginfo));
 527  593          if (error != 0)
 528  594                  return (EFAULT);
 529  595  
 530  596          return (0);
 531  597  }
 532  598  
 533  599  /* ARGSUSED */
 534  600  int
 535  601  ipf_cfwlog_read(dev_t dev, struct uio *uio, cred_t *cp)
↓ open down ↓ 34 lines elided ↑ open up ↑
 570  636                  cfw_evdrops += consumed;
 571  637                  mutex_exit(&cfw_ringlock);
 572  638          }
 573  639          return (ue.ue_error);
 574  640  }
 575  641  
 576  642  #else
 577  643  
 578  644  /* Blank stubs to satisfy userland's test compilations. */
 579  645  
      646 +int
      647 +ipf_cfw_ring_resize(uint32_t a)
      648 +{
      649 +        return (0);
      650 +}
      651 +
 580  652  void
 581  653  ipf_log_cfwlog(struct ipstate *a, uint_t b, ipf_stack_t *c)
 582  654  {
 583  655  }
 584  656  
 585  657  void
 586  658  ipf_block_cfwlog(frentry_t *a, fr_info_t *b, ipf_stack_t *c)
 587  659  {
 588  660  }
 589  661  
 590  662  #endif  /* _KERNEL */
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX