Add per-TDB counters and a new SADB extension to export them to
authormpi <mpi@openbsd.org>
Tue, 28 Aug 2018 15:15:02 +0000 (15:15 +0000)
committermpi <mpi@openbsd.org>
Tue, 28 Aug 2018 15:15:02 +0000 (15:15 +0000)
userland.

Inputs from markus@, ok sthen@

14 files changed:
sys/net/pfkeyv2.c
sys/net/pfkeyv2.h
sys/net/pfkeyv2_convert.c
sys/netinet/ip_ah.c
sys/netinet/ip_esp.c
sys/netinet/ip_ipcomp.c
sys/netinet/ip_ipip.c
sys/netinet/ip_ipsp.c
sys/netinet/ip_ipsp.h
sys/netinet/ip_output.c
sys/netinet/ipsec_input.c
sys/netinet/ipsec_output.c
sys/netinet6/ip6_output.c
sys/sys/percpu.h

index cba1d67..10ebbf9 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfkeyv2.c,v 1.189 2018/07/10 20:28:34 claudio Exp $ */
+/* $OpenBSD: pfkeyv2.c,v 1.190 2018/08/28 15:15:02 mpi Exp $ */
 
 /*
  *     @(#)COPYRIGHT   1.1 (NRL) 17 January 1995
@@ -793,7 +793,8 @@ pfkeyv2_get(struct tdb *sa, void **headers, void **buffer, int *lenp)
        void *p;
 
        /* Find how much space we need */
-       i = sizeof(struct sadb_sa) + sizeof(struct sadb_lifetime);
+       i = sizeof(struct sadb_sa) + sizeof(struct sadb_lifetime) +
+           sizeof(struct sadb_x_counter);
 
        if (sa->tdb_soft_allocations || sa->tdb_soft_bytes ||
            sa->tdb_soft_timeout || sa->tdb_soft_first_use)
@@ -955,6 +956,9 @@ pfkeyv2_get(struct tdb *sa, void **headers, void **buffer, int *lenp)
        }
 #endif
 
+       headers[SADB_X_EXT_COUNTER] = p;
+       export_counter(&p, sa);
+
        rval = 0;
 
  ret:
index 5b80195..7c5d9a6 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfkeyv2.h,v 1.79 2017/11/20 10:56:51 mpi Exp $ */
+/* $OpenBSD: pfkeyv2.h,v 1.80 2018/08/28 15:15:02 mpi Exp $ */
 /*
  *     @(#)COPYRIGHT   1.1 (NRL) January 1998
  *
@@ -218,6 +218,19 @@ struct sadb_x_tap {
        u_int32_t sadb_x_tap_unit;
 };
 
+struct sadb_x_counter {
+       uint16_t  sadb_x_counter_len;
+       uint16_t  sadb_x_counter_exttype;
+       uint64_t  sadb_x_counter_ipackets;      /* Input IPsec packets */
+       uint64_t  sadb_x_counter_opackets;      /* Output IPsec packets */
+       uint64_t  sadb_x_counter_ibytes;        /* Input bytes */
+       uint64_t  sadb_x_counter_obytes;        /* Output bytes */
+       uint64_t  sadb_x_counter_idrops;        /* Dropped on input */
+       uint64_t  sadb_x_counter_odrops;        /* Dropped on output */
+       uint64_t  sadb_x_counter_idecompbytes;  /* Input bytes, decompressed */
+       uint64_t  sadb_x_counter_ouncompbytes;  /* Output bytes, uncompressed */
+};
+
 #ifdef _KERNEL
 #define SADB_X_GETSPROTO(x) \
        ( (x) == SADB_SATYPE_AH ? IPPROTO_AH :\
@@ -262,7 +275,8 @@ struct sadb_x_tap {
 #define SADB_X_EXT_TAG                33
 #define SADB_X_EXT_TAP                34
 #define SADB_X_EXT_SATYPE2            35
-#define SADB_EXT_MAX                  35
+#define SADB_X_EXT_COUNTER            36
+#define SADB_EXT_MAX                  36
 
 /* Fix pfkeyv2.c struct pfkeyv2_socket if SATYPE_MAX > 31 */
 #define SADB_SATYPE_UNSPEC              0
@@ -396,6 +410,7 @@ void export_udpencap(void **, struct tdb *);
 void export_tag(void **, struct tdb *);
 void export_tap(void **, struct tdb *);
 void export_satype(void **, struct tdb *);
+void export_counter(void **, struct tdb *);
 
 void import_address(struct sockaddr *, struct sadb_address *);
 void import_identities(struct ipsec_ids **, int, struct sadb_ident *,
index 3656994..dff1984 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pfkeyv2_convert.c,v 1.63 2018/01/11 16:02:31 bluhm Exp $      */
+/*     $OpenBSD: pfkeyv2_convert.c,v 1.64 2018/08/28 15:15:02 mpi Exp $        */
 /*
  * The author of this code is Angelos D. Keromytis (angelos@keromytis.org)
  *
@@ -898,3 +898,22 @@ export_satype(void **p, struct tdb *tdb)
        sab->sadb_protocol_proto = tdb->tdb_satype;
        *p += sizeof(struct sadb_protocol);
 }
+
+void
+export_counter(void **p, struct tdb *tdb)
+{
+       struct sadb_x_counter *scnt = (struct sadb_x_counter *)*p;
+
+       scnt->sadb_x_counter_len =
+           sizeof(struct sadb_x_counter) / sizeof(uint64_t);
+       scnt->sadb_x_counter_exttype = SADB_X_EXT_COUNTER;
+       scnt->sadb_x_counter_ipackets = tdb->tdb_ipackets;
+       scnt->sadb_x_counter_opackets = tdb->tdb_opackets;
+       scnt->sadb_x_counter_ibytes = tdb->tdb_ibytes;
+       scnt->sadb_x_counter_obytes = tdb->tdb_obytes;
+       scnt->sadb_x_counter_idrops = tdb->tdb_idrops;
+       scnt->sadb_x_counter_odrops = tdb->tdb_odrops;
+       scnt->sadb_x_counter_idecompbytes = tdb->tdb_idecompbytes;
+       scnt->sadb_x_counter_ouncompbytes = tdb->tdb_ouncompbytes;
+       *p += sizeof(struct sadb_x_counter);
+}
index 1be8d72..533cdf3 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip_ah.c,v 1.142 2018/07/12 15:51:50 mpi Exp $ */
+/*     $OpenBSD: ip_ah.c,v 1.143 2018/08/28 15:15:02 mpi Exp $ */
 /*
  * The authors of this code are John Ioannidis (ji@tla.org),
  * Angelos D. Keromytis (kermit@csd.uch.gr) and
@@ -529,6 +529,7 @@ ah_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
        u_int32_t btsx, esn;
        u_int8_t hl;
        int error, rplen;
+       u_int64_t ibytes;
 #ifdef ENCDEBUG
        char buf[INET6_ADDRSTRLEN];
 #endif
@@ -605,9 +606,10 @@ ah_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
        }
 
        /* Update the counters. */
-       tdb->tdb_cur_bytes +=
-           (m->m_pkthdr.len - skip - hl * sizeof(u_int32_t));
-       ahstat_add(ahs_ibytes, m->m_pkthdr.len - skip - hl * sizeof(u_int32_t));
+       ibytes = (m->m_pkthdr.len - skip - hl * sizeof(u_int32_t));
+       tdb->tdb_cur_bytes += ibytes;
+       tdb->tdb_ibytes += ibytes;
+       ahstat_add(ahs_ibytes, ibytes);
 
        /* Hard expiration. */
        if (tdb->tdb_flags & TDBF_BYTES &&
index 990ceb5..03c2491 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip_esp.c,v 1.157 2018/07/12 15:51:50 mpi Exp $ */
+/*     $OpenBSD: ip_esp.c,v 1.158 2018/08/28 15:15:02 mpi Exp $ */
 /*
  * The authors of this code are John Ioannidis (ji@tla.org),
  * Angelos D. Keromytis (kermit@csd.uch.gr) and
@@ -338,6 +338,7 @@ esp_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
        struct tdb_crypto *tc = NULL;
        int plen, alen, hlen, error;
        u_int32_t btsx, esn;
+       u_int64_t ibytes;
 #ifdef ENCDEBUG
        char buf[INET6_ADDRSTRLEN];
 #endif
@@ -415,8 +416,10 @@ esp_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
        }
 
        /* Update the counters */
-       tdb->tdb_cur_bytes += m->m_pkthdr.len - skip - hlen - alen;
-       espstat_add(esps_ibytes, m->m_pkthdr.len - skip - hlen - alen);
+       ibytes = m->m_pkthdr.len - skip - hlen - alen;
+       tdb->tdb_cur_bytes += ibytes;
+       tdb->tdb_ibytes += ibytes;
+       espstat_add(esps_ibytes, ibytes);
 
        /* Hard expiration */
        if ((tdb->tdb_flags & TDBF_BYTES) &&
index a5770ae..7c3a105 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ipcomp.c,v 1.64 2018/07/16 07:49:31 mpi Exp $ */
+/* $OpenBSD: ip_ipcomp.c,v 1.65 2018/08/28 15:15:02 mpi Exp $ */
 
 /*
  * Copyright (c) 2001 Jean-Jacques Bernard-Gundol (jj@wabbitt.org)
@@ -186,6 +186,7 @@ ipcomp_input_cb(struct tdb *tdb, struct tdb_crypto *tc, struct mbuf *m, int clen
 {
        int skip, protoff, roff, hlen = IPCOMP_HLENGTH;
        u_int8_t nproto;
+       u_int64_t ibytes;
        struct mbuf *m1, *mo;
        struct ipcomp  *ipcomp;
        caddr_t addr;
@@ -199,8 +200,10 @@ ipcomp_input_cb(struct tdb *tdb, struct tdb_crypto *tc, struct mbuf *m, int clen
        protoff = tc->tc_protoff;
 
        /* update the counters */
-       tdb->tdb_cur_bytes += m->m_pkthdr.len - (skip + hlen);
-       ipcompstat_add(ipcomps_ibytes, m->m_pkthdr.len - (skip + hlen));
+       ibytes = m->m_pkthdr.len - (skip + hlen);
+       tdb->tdb_cur_bytes += ibytes;
+       tdb->tdb_ibytes += ibytes;
+       ipcompstat_add(ipcomps_ibytes, ibytes);
 
        /* Hard expiration */
        if ((tdb->tdb_flags & TDBF_BYTES) &&
index 7b55255..60d6efd 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip_ipip.c,v 1.87 2017/10/09 08:35:38 mpi Exp $ */
+/*     $OpenBSD: ip_ipip.c,v 1.88 2018/08/28 15:15:02 mpi Exp $ */
 /*
  * The authors of this code are John Ioannidis (ji@tla.org),
  * Angelos D. Keromytis (kermit@csd.uch.gr) and
@@ -331,11 +331,9 @@ int
 ipip_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int dummy,
     int dummy2)
 {
-       u_int8_t tp, otos;
-
-       u_int8_t itos;
+       u_int8_t tp, otos, itos;
+       u_int64_t obytes;
        struct ip *ipo;
-
 #ifdef INET6
        struct ip6_hdr *ip6, *ip6o;
 #endif /* INET6 */
@@ -525,21 +523,20 @@ ipip_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int dummy,
        *mp = m;
 
        if (tdb->tdb_dst.sa.sa_family == AF_INET) {
+               obytes = m->m_pkthdr.len - sizeof(struct ip);
                if (tdb->tdb_xform->xf_type == XF_IP4)
-                       tdb->tdb_cur_bytes +=
-                           m->m_pkthdr.len - sizeof(struct ip);
+                       tdb->tdb_cur_bytes += obytes;
 
-               ipipstat_add(ipips_obytes, m->m_pkthdr.len - sizeof(struct ip));
+               ipipstat_add(ipips_obytes, obytes);
        }
 
 #ifdef INET6
        if (tdb->tdb_dst.sa.sa_family == AF_INET6) {
+               obytes = m->m_pkthdr.len - sizeof(struct ip6_hdr);
                if (tdb->tdb_xform->xf_type == XF_IP4)
-                       tdb->tdb_cur_bytes +=
-                           m->m_pkthdr.len - sizeof(struct ip6_hdr);
+                       tdb->tdb_cur_bytes += obytes;
 
-               ipipstat_add(ipips_obytes,
-                   m->m_pkthdr.len - sizeof(struct ip6_hdr));
+               ipipstat_add(ipips_obytes, obytes);
        }
 #endif /* INET6 */
 
index c3facff..a2c1d99 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip_ipsp.c,v 1.231 2018/05/19 12:34:35 mpi Exp $       */
+/*     $OpenBSD: ip_ipsp.c,v 1.232 2018/08/28 15:15:02 mpi Exp $       */
 /*
  * The authors of this code are John Ioannidis (ji@tla.org),
  * Angelos D. Keromytis (kermit@csd.uch.gr),
@@ -708,6 +708,8 @@ puttdb(struct tdb *tdbp)
        tdbsrc[hashval] = tdbp;
 
        tdb_count++;
+       if ((tdbp->tdb_flags & (TDBF_INVALID|TDBF_TUNNELING)) == TDBF_TUNNELING)
+               ipsecstat_inc(ipsec_tunnels);
 
        ipsec_last_added = time_second;
 }
@@ -775,6 +777,11 @@ tdb_unlink(struct tdb *tdbp)
 
        tdbp->tdb_snext = NULL;
        tdb_count--;
+       if ((tdbp->tdb_flags & (TDBF_INVALID|TDBF_TUNNELING)) ==
+           TDBF_TUNNELING) {
+               ipsecstat_dec(ipsec_tunnels);
+               ipsecstat_inc(ipsec_prevtunnels);
+       }
 }
 
 void
index ba8652e..49c9d66 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip_ipsp.h,v 1.192 2018/07/12 15:51:50 mpi Exp $       */
+/*     $OpenBSD: ip_ipsp.h,v 1.193 2018/08/28 15:15:02 mpi Exp $       */
 /*
  * The authors of this code are John Ioannidis (ji@tla.org),
  * Angelos D. Keromytis (kermit@csd.uch.gr),
@@ -122,6 +122,8 @@ struct sockaddr_encap {
 #define        IPSP_DIRECTION_OUT      0x2
 
 struct ipsecstat {
+       uint64_t        ipsec_tunnels;          /* Number of active tunnels */
+       uint64_t        ipsec_prevtunnels;      /* Past number of tunnels */
        uint64_t        ipsec_ipackets;         /* Input IPsec packets */
        uint64_t        ipsec_opackets;         /* Output IPsec packets */
        uint64_t        ipsec_ibytes;           /* Input bytes */
@@ -135,6 +137,17 @@ struct ipsecstat {
        uint64_t        ipsec_noxform;          /* Crypto error */
 };
 
+struct tdb_data {
+       uint64_t        tdd_ipackets;           /* Input IPsec packets */
+       uint64_t        tdd_opackets;           /* Output IPsec packets */
+       uint64_t        tdd_ibytes;             /* Input bytes */
+       uint64_t        tdd_obytes;             /* Output bytes */
+       uint64_t        tdd_idrops;             /* Dropped on input */
+       uint64_t        tdd_odrops;             /* Dropped on output */
+       uint64_t        tdd_idecompbytes;       /* Input bytes, decompressed */
+       uint64_t        tdd_ouncompbytes;       /* Output bytes, uncompressed */
+};
+
 #ifdef _KERNEL
 
 #include <sys/timeout.h>
@@ -144,6 +157,8 @@ struct ipsecstat {
 #include <sys/percpu.h>
 
 enum ipsec_counters {
+       ipsec_tunnels,
+       ipsec_prevtunnels,
        ipsec_ipackets,
        ipsec_opackets,
        ipsec_ibytes,
@@ -166,6 +181,12 @@ ipsecstat_inc(enum ipsec_counters c)
        counters_inc(ipseccounters, c);
 }
 
+static inline void
+ipsecstat_dec(enum ipsec_counters c)
+{
+       counters_dec(ipseccounters, c);
+}
+
 static inline void
 ipsecstat_add(enum ipsec_counters c, uint64_t v)
 {
@@ -350,6 +371,7 @@ struct tdb {                                /* tunnel descriptor block */
        u_int64_t       tdb_last_used;  /* When was this SA last used */
        u_int64_t       tdb_last_marked;/* Last SKIPCRYPTO status change */
 
+       struct tdb_data tdb_data;       /* stats about this TDB */
        u_int64_t       tdb_cryptoid;   /* Crypto session ID */
 
        u_int32_t       tdb_spi;        /* SPI */
@@ -394,6 +416,14 @@ struct tdb {                               /* tunnel descriptor block */
        TAILQ_HEAD(tdb_policy_head, ipsec_policy)       tdb_policy_head;
        TAILQ_ENTRY(tdb)        tdb_sync_entry;
 };
+#define tdb_ipackets           tdb_data.tdd_ipackets
+#define tdb_opackets           tdb_data.tdd_opackets
+#define tdb_ibytes             tdb_data.tdd_ibytes
+#define tdb_obytes             tdb_data.tdd_obytes
+#define tdb_idrops             tdb_data.tdd_idrops
+#define tdb_odrops             tdb_data.tdd_odrops
+#define tdb_idecompbytes       tdb_data.tdd_idecompbytes
+#define tdb_ouncompbytes       tdb_data.tdd_ouncompbytes
 
 
 struct tdb_ident {
index 162803b..c963f7c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip_output.c,v 1.347 2018/07/12 15:51:50 mpi Exp $     */
+/*     $OpenBSD: ip_output.c,v 1.348 2018/08/28 15:15:02 mpi Exp $     */
 /*     $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $  */
 
 /*
@@ -635,8 +635,10 @@ ip_output_ipsec_send(struct tdb *tdb, struct mbuf *m, struct route *ro, int fwd)
 
        /* Callee frees mbuf */
        error = ipsp_process_packet(m, tdb, AF_INET, 0);
-       if (error)
+       if (error) {
                ipsecstat_inc(ipsec_odrops);
+               tdb->tdb_odrops++;
+       }
        return error;
 }
 #endif /* IPSEC */
index fb69adc..785b90b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ipsec_input.c,v 1.165 2018/07/11 09:07:59 mpi Exp $   */
+/*     $OpenBSD: ipsec_input.c,v 1.166 2018/08/28 15:15:02 mpi Exp $   */
 /*
  * The authors of this code are John Ioannidis (ji@tla.org),
  * Angelos D. Keromytis (kermit@csd.uch.gr) and
@@ -325,17 +325,24 @@ ipsec_common_input(struct mbuf *m, int skip, int protoff, int af, int sproto,
                            tdbp->tdb_soft_first_use);
        }
 
+       tdbp->tdb_ipackets++;
+       tdbp->tdb_ibytes += m->m_pkthdr.len;
+
        /*
         * Call appropriate transform and return -- callback takes care of
         * everything else.
         */
        error = (*(tdbp->tdb_xform->xf_input))(m, tdbp, skip, protoff);
-       if (error)
+       if (error) {
                ipsecstat_inc(ipsec_idrops);
+               tdbp->tdb_idrops++;
+       }
        return error;
 
  drop:
        ipsecstat_inc(ipsec_idrops);
+       if (tdbp != NULL)
+               tdbp->tdb_idrops++;
        m_freem(m);
        return error;
 }
@@ -400,14 +407,18 @@ ipsec_input_cb(struct cryptop *crp)
        }
 
        NET_UNLOCK();
-       if (error)
+       if (error) {
                ipsecstat_inc(ipsec_idrops);
+               tdb->tdb_idrops++;
+       }
        return;
 
  baddone:
        NET_UNLOCK();
  droponly:
        ipsecstat_inc(ipsec_idrops);
+       if (tdb != NULL)
+               tdb->tdb_idrops++;
        free(tc, M_XDATA, 0);
        m_freem(m);
        crypto_freereq(crp);
@@ -651,6 +662,7 @@ ipsec_common_input_cb(struct mbuf *m, struct tdb *tdbp, int skip, int protoff)
                m->m_flags |= M_TUNNEL;
 
        ipsecstat_add(ipsec_idecompbytes, m->m_pkthdr.len);
+       tdbp->tdb_idecompbytes += m->m_pkthdr.len;
 
 #if NBPFILTER > 0
        if ((encif = enc_getif(tdbp->tdb_rdomain, tdbp->tdb_tap)) != NULL) {
index 840903d..c477793 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ipsec_output.c,v 1.73 2018/07/12 15:51:50 mpi Exp $ */
+/*     $OpenBSD: ipsec_output.c,v 1.74 2018/08/28 15:15:02 mpi Exp $ */
 /*
  * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
  *
@@ -361,6 +361,7 @@ ipsp_process_packet(struct mbuf *m, struct tdb *tdb, int af, int tunalready)
        }
 
         ipsecstat_add(ipsec_ouncompbytes, m->m_pkthdr.len);
+        tdb->tdb_ouncompbytes += m->m_pkthdr.len;
 
        /* Non expansion policy for IPCOMP */
        if (tdb->tdb_sproto == IPPROTO_IPCOMP) {
@@ -441,13 +442,17 @@ ipsec_output_cb(struct cryptop *crp)
        }
 
        NET_UNLOCK();
-       if (error)
+       if (error) {
                ipsecstat_inc(ipsec_odrops);
+               tdb->tdb_odrops++;
+       }
        return;
 
  baddone:
        NET_UNLOCK();
  droponly:
+       if (tdb != NULL)
+               tdb->tdb_odrops++;
        m_freem(m);
        free(tc, M_XDATA, 0);
        crypto_freereq(crp);
@@ -572,14 +577,16 @@ ipsp_process_done(struct mbuf *m, struct tdb *tdb)
 
        m_tag_prepend(m, mtag);
 
+       ipsecstat_inc(ipsec_opackets);
+       ipsecstat_add(ipsec_obytes, m->m_pkthdr.len);
+       tdb->tdb_opackets++;
+       tdb->tdb_obytes += m->m_pkthdr.len;
+
        /* If there's another (bundled) TDB to apply, do so. */
        if (tdb->tdb_onext)
                return ipsp_process_packet(m, tdb->tdb_onext,
                    tdb->tdb_dst.sa.sa_family, 0);
 
-       ipsecstat_inc(ipsec_opackets);
-       ipsecstat_add(ipsec_obytes, m->m_pkthdr.len);
-
 #if NPF > 0
        /* Add pf tag if requested. */
        pf_tag_packet(m, tdb->tdb_tag, -1);
index 4b9fffb..e6177f4 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip6_output.c,v 1.238 2018/07/12 15:51:50 mpi Exp $    */
+/*     $OpenBSD: ip6_output.c,v 1.239 2018/08/28 15:15:02 mpi Exp $    */
 /*     $KAME: ip6_output.c,v 1.172 2001/03/25 09:55:56 itojun Exp $    */
 
 /*
@@ -2788,8 +2788,10 @@ ip6_output_ipsec_send(struct tdb *tdb, struct mbuf *m, int tunalready, int fwd)
 
        /* Callee frees mbuf */
        error = ipsp_process_packet(m, tdb, AF_INET6, tunalready);
-       if (error)
+       if (error) {
                ipsecstat_inc(ipsec_odrops);
+               tdb->tdb_odrops++;
+       }
        return error;
 }
 #endif /* IPSEC */
index 90af5c6..53a1a88 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: percpu.h,v 1.7 2017/02/23 00:15:12 dlg Exp $ */
+/*     $OpenBSD: percpu.h,v 1.8 2018/08/28 15:15:02 mpi Exp $ */
 
 /*
  * Copyright (c) 2016 David Gwynne <dlg@openbsd.org>
@@ -150,6 +150,17 @@ counters_inc(struct cpumem *cm, unsigned int c)
        counters_leave(&ref, cm);
 }
 
+static inline void
+counters_dec(struct cpumem *cm, unsigned int c)
+{
+       struct counters_ref ref;
+       uint64_t *counters;
+
+       counters = counters_enter(&ref, cm);
+       counters[c]--;
+       counters_leave(&ref, cm);
+}
+
 static inline void
 counters_add(struct cpumem *cm, unsigned int c, uint64_t v)
 {