This one is a bit weird, the driver doesn't just increment the stats but
also uses them at runtime, hence the additional helper functions.
ok?
Index: net/if_pflow.h
===================================================================
RCS file: /d/cvs/src/sys/net/if_pflow.h,v
retrieving revision 1.15
diff -u -p -r1.15 if_pflow.h
--- net/if_pflow.h 24 Jan 2017 10:08:30 -0000 1.15
+++ net/if_pflow.h 18 Feb 2017 13:41:35 -0000
@@ -263,6 +263,25 @@ struct pflowreq {
};
#ifdef _KERNEL
+
+#include <sys/percpu.h>
+
+enum pflowstat_counters {
+ pflows_flows,
+ pflows_packets,
+ pflows_onomem,
+ pflows_oerrors,
+ pflows_ncounters,
+};
+
+extern struct cpumem *pflowcounters;
+
+static inline void
+pflowstat_inc(enum pflowstat_counters c)
+{
+ counters_inc(pflowcounters, c);
+}
+
int export_pflow(struct pf_state *);
int pflow_sysctl(int *, u_int, void *, size_t *, void *, size_t);
#endif /* _KERNEL */
Index: net/if_pflow.c
===================================================================
RCS file: /d/cvs/src/sys/net/if_pflow.c,v
retrieving revision 1.74
diff -u -p -r1.74 if_pflow.c
--- net/if_pflow.c 16 Feb 2017 10:15:12 -0000 1.74
+++ net/if_pflow.c 18 Feb 2017 13:41:35 -0000
@@ -62,7 +62,7 @@
#endif
SLIST_HEAD(, pflow_softc) pflowif_list;
-struct pflowstats pflowstats;
+struct cpumem *pflowcounters;
void pflowattach(int);
int pflow_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
@@ -73,6 +73,8 @@ int pflow_set(struct pflow_softc *, stru
void pflow_init_timeouts(struct pflow_softc *);
int pflow_calc_mtu(struct pflow_softc *, int, int);
void pflow_setmtu(struct pflow_softc *, int);
+uint64_t pflowstat_get_flows(void);
+void pflowstat_update_flows(uint64_t);
int pflowvalidsockaddr(const struct sockaddr *, int);
int pflowioctl(struct ifnet *, u_long, caddr_t);
@@ -114,6 +116,7 @@ pflowattach(int npflow)
{
SLIST_INIT(&pflowif_list);
if_clone_attach(&pflow_cloner);
+ pflowcounters = counters_alloc(pflows_ncounters);
}
int
@@ -283,6 +286,30 @@ pflow_clone_destroy(struct ifnet *ifp)
return (error);
}
+uint64_t
+pflowstat_get_flows(void)
+{
+ uint64_t *counters, flows;
+ struct counters_ref ref;
+
+ counters = counters_enter(&ref, pflowcounters);
+ flows = counters[pflows_flows];
+ counters_leave(&ref, pflowcounters);
+ return flows;
+}
+
+void
+pflowstat_update_flows(uint64_t gcounter)
+{
+ uint64_t *counters;
+ struct counters_ref ref;
+
+ counters = counters_enter(&ref, pflowcounters);
+ if (counters[pflows_flows] == gcounter)
+ counters[pflows_flows]++;
+ counters_leave(&ref, pflowcounters);
+}
+
int
pflowvalidsockaddr(const struct sockaddr *sa, int ignore_port)
{
@@ -460,7 +487,7 @@ pflowioctl(struct ifnet *ifp, u_long cmd
case SIOCSIFFLAGS:
if ((ifp->if_flags & IFF_UP) && sc->so != NULL) {
ifp->if_flags |= IFF_RUNNING;
- sc->sc_gcounter=pflowstats.pflow_flows;
+ sc->sc_gcounter = pflowstat_get_flows();
/* send templates on startup */
if (sc->sc_version == PFLOW_PROTO_10) {
/* XXXSMP breaks atomicity */
@@ -518,7 +545,7 @@ pflowioctl(struct ifnet *ifp, u_long cmd
if ((ifp->if_flags & IFF_UP) && sc->so != NULL) {
ifp->if_flags |= IFF_RUNNING;
- sc->sc_gcounter=pflowstats.pflow_flows;
+ sc->sc_gcounter = pflowstat_get_flows();
if (sc->sc_version == PFLOW_PROTO_10) {
s = splnet();
pflow_sendout_ipfix_tmpl(sc);
@@ -619,14 +646,14 @@ pflow_get_mbuf(struct pflow_softc *sc, u
MGETHDR(m, M_DONTWAIT, MT_DATA);
if (m == NULL) {
- pflowstats.pflow_onomem++;
+ pflowstat_inc(pflows_onomem);
return (NULL);
}
MCLGET(m, M_DONTWAIT);
if ((m->m_flags & M_EXT) == 0) {
m_free(m);
- pflowstats.pflow_onomem++;
+ pflowstat_inc(pflows_onomem);
return (NULL);
}
@@ -865,8 +892,7 @@ copy_flow_to_m(struct pflow_flow *flow,
(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_update_flows(sc->sc_gcounter);
sc->sc_gcounter++;
sc->sc_count++;
@@ -896,8 +922,7 @@ copy_flow_ipfix_4_to_m(struct pflow_ipfi
(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_update_flows(sc->sc_gcounter);
sc->sc_gcounter++;
sc->sc_count4++;
@@ -926,8 +951,7 @@ copy_flow_ipfix_6_to_m(struct pflow_ipfi
(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_update_flows(sc->sc_gcounter);
sc->sc_gcounter++;
sc->sc_count6++;
@@ -1086,7 +1110,7 @@ pflow_sendout_v5(struct pflow_softc *sc)
return (0);
}
- pflowstats.pflow_packets++;
+ pflowstat_inc(pflows_packets);
h = mtod(m, struct pflow_header *);
h->count = htons(sc->sc_count);
@@ -1141,14 +1165,14 @@ pflow_sendout_ipfix(struct pflow_softc *
return (0);
}
- pflowstats.pflow_packets++;
+ pflowstat_inc(pflows_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(pflows_onomem);
return (ENOBUFS);
}
h10 = mtod(m, struct pflow_v10_header *);
@@ -1182,12 +1206,12 @@ pflow_sendout_ipfix_tmpl(struct pflow_so
m_freem(m);
return (0);
}
- pflowstats.pflow_packets++;
+ pflowstat_inc(pflows_packets);
/* populate pflow_header */
M_PREPEND(m, sizeof(struct pflow_v10_header), M_DONTWAIT);
if (m == NULL) {
- pflowstats.pflow_onomem++;
+ pflowstat_inc(pflows_onomem);
return (ENOBUFS);
}
h10 = mtod(m, struct pflow_v10_header *);
@@ -1216,6 +1240,17 @@ pflow_sendout_mbuf(struct pflow_softc *s
}
int
+pflow_sysctl_pflowstat(void *oldp, size_t *oldlenp, void *newp)
+{
+ struct pflowstats pflowstat;
+
+ CTASSERT(sizeof(pflowstat) == (pflows_ncounters * sizeof(uint64_t)));
+ counters_read(pflowcounters, (uint64_t *)&pflowstat, pflows_ncounters);
+ return (sysctl_rdstruct(oldp, oldlenp, newp,
+ &pflowstat, sizeof(pflowstat)));
+}
+
+int
pflow_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
void *newp, size_t newlen)
{
@@ -1224,10 +1259,7 @@ pflow_sysctl(int *name, u_int namelen, v
switch (name[0]) {
case NET_PFLOW_STATS:
- if (newp != NULL)
- return (EPERM);
- return (sysctl_struct(oldp, oldlenp, newp, newlen,
- &pflowstats, sizeof(pflowstats)));
+ return (pflow_sysctl_pflowstat(oldp, oldlenp, newp));
default:
return (EOPNOTSUPP);
}
--
jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF DDCC 0DFA 74AE 1524 E7EE