-/* $OpenBSD: if_pflow.c,v 1.103 2023/12/11 14:25:09 mvs Exp $ */
+/* $OpenBSD: if_pflow.c,v 1.104 2023/12/12 00:03:31 mvs Exp $ */
/*
* Copyright (c) 2011 Florian Obser <florian@narrans.de>
#endif
SMR_SLIST_HEAD(, pflow_softc) pflowif_list;
-struct pflowstats pflowstats;
+
+enum pflowstat_counters {
+ pflow_flows,
+ pflow_packets,
+ pflow_onomem,
+ pflow_oerrors,
+ pflow_ncounters,
+};
+
+struct cpumem *pflow_counters;
+
+static inline void
+pflowstat_inc(enum pflowstat_counters c)
+{
+ counters_inc(pflow_counters, c);
+}
void pflowattach(int);
int pflow_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
pflowattach(int npflow)
{
SMR_SLIST_INIT(&pflowif_list);
+ pflow_counters = counters_alloc(pflow_ncounters);
if_clone_attach(&pflow_cloner);
}
if ((ifp->if_flags & IFF_UP) && sc->so != NULL) {
ifp->if_flags |= IFF_RUNNING;
mtx_enter(&sc->sc_mtx);
- sc->sc_gcounter = pflowstats.pflow_flows;
/* send templates on startup */
if (sc->sc_version == PFLOW_PROTO_10)
pflow_sendout_ipfix_tmpl(sc);
if ((ifp->if_flags & IFF_UP) && sc->so != NULL) {
ifp->if_flags |= IFF_RUNNING;
mtx_enter(&sc->sc_mtx);
- sc->sc_gcounter = pflowstats.pflow_flows;
if (sc->sc_version == PFLOW_PROTO_10)
pflow_sendout_ipfix_tmpl(sc);
mtx_leave(&sc->sc_mtx);
MGETHDR(m, M_DONTWAIT, MT_DATA);
if (m == NULL) {
- pflowstats.pflow_onomem++;
+ pflowstat_inc(pflow_onomem);
return (NULL);
}
MCLGET(m, M_DONTWAIT);
if ((m->m_flags & M_EXT) == 0) {
m_free(m);
- pflowstats.pflow_onomem++;
+ pflowstat_inc(pflow_onomem);
return (NULL);
}
(sc->sc_count * sizeof(struct pflow_flow)),
sizeof(struct pflow_flow), flow, M_NOWAIT);
- if (pflowstats.pflow_flows == sc->sc_gcounter)
- pflowstats.pflow_flows++;
+ pflowstat_inc(pflow_flows);
sc->sc_gcounter++;
sc->sc_count++;
(sc->sc_count4 * sizeof(struct pflow_ipfix_flow4)),
sizeof(struct pflow_ipfix_flow4), flow, M_NOWAIT);
- if (pflowstats.pflow_flows == sc->sc_gcounter)
- pflowstats.pflow_flows++;
+ pflowstat_inc(pflow_flows);
sc->sc_gcounter++;
sc->sc_count4++;
(sc->sc_count6 * sizeof(struct pflow_ipfix_flow6)),
sizeof(struct pflow_ipfix_flow6), flow, M_NOWAIT);
- if (pflowstats.pflow_flows == sc->sc_gcounter)
- pflowstats.pflow_flows++;
+ pflowstat_inc(pflow_flows);
sc->sc_gcounter++;
sc->sc_count6++;
return (0);
}
- pflowstats.pflow_packets++;
+ pflowstat_inc(pflow_packets);
h = mtod(m, struct pflow_header *);
h->count = htons(sc->sc_count);
return (0);
}
- pflowstats.pflow_packets++;
+ pflowstat_inc(pflow_packets);
set_hdr = mtod(m, struct pflow_set_header *);
set_hdr->set_length = htons(set_length);
/* populate pflow_header */
M_PREPEND(m, sizeof(struct pflow_v10_header), M_DONTWAIT);
if (m == NULL) {
- pflowstats.pflow_onomem++;
+ pflowstat_inc(pflow_onomem);
return (ENOBUFS);
}
h10 = mtod(m, struct pflow_v10_header *);
m_freem(m);
return (0);
}
- pflowstats.pflow_packets++;
+ pflowstat_inc(pflow_packets);
/* populate pflow_header */
M_PREPEND(m, sizeof(struct pflow_v10_header), M_DONTWAIT);
if (m == NULL) {
- pflowstats.pflow_onomem++;
+ pflowstat_inc(pflow_onomem);
return (ENOBUFS);
}
h10 = mtod(m, struct pflow_v10_header *);
return (ENOTDIR);
switch (name[0]) {
- case NET_PFLOW_STATS:
+ case NET_PFLOW_STATS: {
+ uint64_t counters[pflow_ncounters];
+ struct pflowstats pflowstats;
+
if (newp != NULL)
return (EPERM);
+
+ counters_read(pflow_counters, counters, pflow_ncounters, NULL);
+
+ pflowstats.pflow_flows = counters[pflow_flows];
+ pflowstats.pflow_packets = counters[pflow_packets];
+ pflowstats.pflow_onomem = counters[pflow_onomem];
+ pflowstats.pflow_oerrors = counters[pflow_oerrors];
+
return (sysctl_struct(oldp, oldlenp, newp, newlen,
&pflowstats, sizeof(pflowstats)));
+ }
default:
return (EOPNOTSUPP);
}