mirror of
https://github.com/freebsd/freebsd-src
synced 2024-07-23 11:16:33 +00:00
pflow: Turn `pflowstats' statistics counters into per-CPU counters to make them mpsafe.
The weird interactions around `pflow_flows' and `sc_gcounter' replaced by simple `pflow_flows' increment. Since the flow sequence is the 32 bits integer, the `sc_gcounter' type replaced by the type of uint32_t. Obtained from: OpenBSD Sponsored by: Rubicon Communications, LLC ("Netgate") Differential Revision: https://reviews.freebsd.org/D43116
This commit is contained in:
parent
34276498fa
commit
2be6f75707
|
@ -244,7 +244,7 @@ struct pflow_softc {
|
|||
unsigned int sc_maxcount4;
|
||||
unsigned int sc_maxcount6;
|
||||
unsigned int sc_maxcount_nat4;
|
||||
u_int64_t sc_gcounter;
|
||||
u_int32_t sc_gcounter;
|
||||
u_int32_t sc_sequence;
|
||||
struct callout sc_tmo;
|
||||
struct callout sc_tmo6;
|
||||
|
|
|
@ -89,6 +89,7 @@ static int pflow_sendout_v5(struct pflow_softc *);
|
|||
static int pflow_sendout_ipfix(struct pflow_softc *, enum pflow_family_t);
|
||||
static int pflow_sendout_ipfix_tmpl(struct pflow_softc *);
|
||||
static int pflow_sendout_mbuf(struct pflow_softc *, struct mbuf *);
|
||||
static int sysctl_pflowstats(SYSCTL_HANDLER_ARGS);
|
||||
static void pflow_timeout(void *);
|
||||
static void pflow_timeout6(void *);
|
||||
static void pflow_timeout_tmpl(void *);
|
||||
|
@ -119,6 +120,17 @@ static int copy_nat_ipfix_4_to_m(struct pflow_ipfix_nat4 *,
|
|||
|
||||
static const char pflowname[] = "pflow";
|
||||
|
||||
enum pflowstat_counters {
|
||||
pflow_flows,
|
||||
pflow_packets,
|
||||
pflow_onomem,
|
||||
pflow_oerrors,
|
||||
pflow_ncounters,
|
||||
};
|
||||
struct pflowstats_ctr {
|
||||
counter_u64_t c[pflow_ncounters];
|
||||
};
|
||||
|
||||
/**
|
||||
* Locking concept
|
||||
*
|
||||
|
@ -139,7 +151,7 @@ VNET_DEFINE(CK_LIST_HEAD(, pflow_softc), pflowif_list);
|
|||
#define V_pflowif_list VNET(pflowif_list)
|
||||
VNET_DEFINE(struct mtx, pflowif_list_mtx);
|
||||
#define V_pflowif_list_mtx VNET(pflowif_list_mtx)
|
||||
VNET_DEFINE(struct pflowstats, pflowstat);
|
||||
VNET_DEFINE(struct pflowstats_ctr, pflowstat);
|
||||
#define V_pflowstats VNET(pflowstat)
|
||||
|
||||
#define PFLOW_LOCK(_sc) mtx_lock(&(_sc)->sc_lock)
|
||||
|
@ -148,10 +160,16 @@ VNET_DEFINE(struct pflowstats, pflowstat);
|
|||
|
||||
SYSCTL_NODE(_net, OID_AUTO, pflow, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
|
||||
"PFLOW");
|
||||
SYSCTL_STRUCT(_net_pflow, OID_AUTO, stats, CTLFLAG_VNET | CTLFLAG_RW,
|
||||
&VNET_NAME(pflowstat), pflowstats,
|
||||
SYSCTL_PROC(_net_pflow, OID_AUTO, stats, CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE,
|
||||
0, 0, sysctl_pflowstats, "S,pflowstats",
|
||||
"PFLOW statistics (struct pflowstats, net/if_pflow.h)");
|
||||
|
||||
static inline void
|
||||
pflowstat_inc(enum pflowstat_counters c)
|
||||
{
|
||||
counter_u64_add(V_pflowstats.c[c], 1);
|
||||
}
|
||||
|
||||
static void
|
||||
vnet_pflowattach(void)
|
||||
{
|
||||
|
@ -159,6 +177,9 @@ vnet_pflowattach(void)
|
|||
mtx_init(&V_pflowif_list_mtx, "pflow interface list mtx", NULL, MTX_DEF);
|
||||
|
||||
V_pflow_unr = new_unrhdr(0, INT_MAX, &V_pflowif_list_mtx);
|
||||
|
||||
for (int i = 0; i < pflow_ncounters; i++)
|
||||
V_pflowstats.c[i] = counter_u64_alloc(M_WAITOK);
|
||||
}
|
||||
VNET_SYSINIT(vnet_pflowattach, SI_SUB_PROTO_FIREWALL, SI_ORDER_ANY,
|
||||
vnet_pflowattach, NULL);
|
||||
|
@ -175,6 +196,9 @@ vnet_pflowdetach(void)
|
|||
MPASS(CK_LIST_EMPTY(&V_pflowif_list));
|
||||
delete_unrhdr(V_pflow_unr);
|
||||
mtx_destroy(&V_pflowif_list_mtx);
|
||||
|
||||
for (int i = 0; i < pflow_ncounters; i++)
|
||||
counter_u64_free(V_pflowstats.c[i]);
|
||||
}
|
||||
VNET_SYSUNINIT(vnet_pflowdetach, SI_SUB_PROTO_FIREWALL, SI_ORDER_FOURTH,
|
||||
vnet_pflowdetach, NULL);
|
||||
|
@ -538,14 +562,14 @@ pflow_get_mbuf(struct pflow_softc *sc, u_int16_t set_id)
|
|||
|
||||
MGETHDR(m, M_NOWAIT, MT_DATA);
|
||||
if (m == NULL) {
|
||||
V_pflowstats.pflow_onomem++;
|
||||
pflowstat_inc(pflow_onomem);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
MCLGET(m, M_NOWAIT);
|
||||
if ((m->m_flags & M_EXT) == 0) {
|
||||
m_free(m);
|
||||
V_pflowstats.pflow_onomem++;
|
||||
pflowstat_inc(pflow_onomem);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
@ -808,8 +832,7 @@ copy_flow_to_m(struct pflow_flow *flow, struct pflow_softc *sc)
|
|||
(sc->sc_count * sizeof(struct pflow_flow)),
|
||||
sizeof(struct pflow_flow), (caddr_t)flow);
|
||||
|
||||
if (V_pflowstats.pflow_flows == sc->sc_gcounter)
|
||||
V_pflowstats.pflow_flows++;
|
||||
pflowstat_inc(pflow_flows);
|
||||
sc->sc_gcounter++;
|
||||
sc->sc_count++;
|
||||
|
||||
|
@ -839,8 +862,7 @@ copy_flow_ipfix_4_to_m(struct pflow_ipfix_flow4 *flow, struct pflow_softc *sc)
|
|||
(sc->sc_count4 * sizeof(struct pflow_ipfix_flow4)),
|
||||
sizeof(struct pflow_ipfix_flow4), (caddr_t)flow);
|
||||
|
||||
if (V_pflowstats.pflow_flows == sc->sc_gcounter)
|
||||
V_pflowstats.pflow_flows++;
|
||||
pflowstat_inc(pflow_flows);
|
||||
sc->sc_gcounter++;
|
||||
sc->sc_count4++;
|
||||
|
||||
|
@ -869,8 +891,7 @@ copy_flow_ipfix_6_to_m(struct pflow_ipfix_flow6 *flow, struct pflow_softc *sc)
|
|||
(sc->sc_count6 * sizeof(struct pflow_ipfix_flow6)),
|
||||
sizeof(struct pflow_ipfix_flow6), (caddr_t)flow);
|
||||
|
||||
if (V_pflowstats.pflow_flows == sc->sc_gcounter)
|
||||
V_pflowstats.pflow_flows++;
|
||||
pflowstat_inc(pflow_flows);
|
||||
sc->sc_gcounter++;
|
||||
sc->sc_count6++;
|
||||
|
||||
|
@ -905,10 +926,9 @@ copy_nat_ipfix_4_to_m(struct pflow_ipfix_nat4 *nat, const struct pf_kstate *st,
|
|||
sizeof(struct pflow_ipfix_nat4), (caddr_t)nat);
|
||||
sc->sc_count_nat4++;
|
||||
|
||||
if (V_pflowstats.pflow_flows == sc->sc_gcounter)
|
||||
V_pflowstats.pflow_flows++;
|
||||
|
||||
pflowstat_inc(pflow_flows);
|
||||
sc->sc_gcounter++;
|
||||
|
||||
if (sc->sc_count_nat4 >= sc->sc_maxcount_nat4)
|
||||
ret = pflow_sendout_ipfix(sc, PFLOW_NAT4);
|
||||
|
||||
|
@ -1116,7 +1136,7 @@ pflow_sendout_v5(struct pflow_softc *sc)
|
|||
|
||||
sc->sc_mbuf = NULL;
|
||||
|
||||
V_pflowstats.pflow_packets++;
|
||||
pflowstat_inc(pflow_packets);
|
||||
h = mtod(m, struct pflow_header *);
|
||||
h->count = htons(sc->sc_count);
|
||||
|
||||
|
@ -1178,14 +1198,15 @@ pflow_sendout_ipfix(struct pflow_softc *sc, enum pflow_family_t af)
|
|||
panic("Unsupported AF %d", af);
|
||||
}
|
||||
|
||||
V_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_NOWAIT);
|
||||
if (m == NULL) {
|
||||
V_pflowstats.pflow_onomem++;
|
||||
pflowstat_inc(pflow_onomem);
|
||||
return (ENOBUFS);
|
||||
}
|
||||
h10 = mtod(m, struct pflow_v10_header *);
|
||||
|
@ -1215,12 +1236,12 @@ pflow_sendout_ipfix_tmpl(struct pflow_softc *sc)
|
|||
m_copyback(m, 0, sizeof(struct pflow_ipfix_tmpl),
|
||||
(caddr_t)&sc->sc_tmpl_ipfix);
|
||||
|
||||
V_pflowstats.pflow_packets++;
|
||||
pflowstat_inc(pflow_packets);
|
||||
|
||||
/* populate pflow_header */
|
||||
M_PREPEND(m, sizeof(struct pflow_v10_header), M_NOWAIT);
|
||||
if (m == NULL) {
|
||||
V_pflowstats.pflow_onomem++;
|
||||
pflowstat_inc(pflow_onomem);
|
||||
return (ENOBUFS);
|
||||
}
|
||||
h10 = mtod(m, struct pflow_v10_header *);
|
||||
|
@ -1249,6 +1270,23 @@ pflow_sendout_mbuf(struct pflow_softc *sc, struct mbuf *m)
|
|||
return (sosend(sc->so, sc->sc_flowdst, NULL, m, NULL, 0, curthread));
|
||||
}
|
||||
|
||||
static int
|
||||
sysctl_pflowstats(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
struct pflowstats pflowstats;
|
||||
|
||||
pflowstats.pflow_flows =
|
||||
counter_u64_fetch(V_pflowstats.c[pflow_flows]);
|
||||
pflowstats.pflow_packets =
|
||||
counter_u64_fetch(V_pflowstats.c[pflow_packets]);
|
||||
pflowstats.pflow_onomem =
|
||||
counter_u64_fetch(V_pflowstats.c[pflow_onomem]);
|
||||
pflowstats.pflow_oerrors =
|
||||
counter_u64_fetch(V_pflowstats.c[pflow_oerrors]);
|
||||
|
||||
return (sysctl_handle_opaque(oidp, &pflowstats, sizeof(pflowstats), req));
|
||||
}
|
||||
|
||||
static int
|
||||
pflow_nl_list(struct nlmsghdr *hdr, struct nl_pstate *npt)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue