-/* $OpenBSD: if_pflow.c,v 1.97 2022/11/11 10:51:46 dlg Exp $ */
+/* $OpenBSD: if_pflow.c,v 1.98 2022/11/23 15:12:27 mvs Exp $ */
/*
* Copyright (c) 2011 Florian Obser <florian@narrans.de>
struct mbuf *m;
mq_delist(&sc->sc_outputqueue, &ml);
- KERNEL_LOCK();
+ rw_enter_read(&sc->sc_lock);
while ((m = ml_dequeue(&ml)) != NULL) {
pflow_sendout_mbuf(sc, m);
}
- KERNEL_UNLOCK();
+ rw_exit_read(&sc->sc_lock);
}
int
struct pflow_softc *pflowif;
pflowif = malloc(sizeof(*pflowif), M_DEVBUF, M_WAITOK|M_ZERO);
+ rw_init(&pflowif->sc_lock, "pflowlk");
MGET(pflowif->send_nam, M_WAIT, MT_SONAME);
pflowif->sc_version = PFLOW_PROTO_DEFAULT;
mq_init(&pflowif->sc_outputqueue, 8192, IPL_SOFTNET);
pflow_setmtu(pflowif, ETHERMTU);
pflow_init_timeouts(pflowif);
+ if_counters_alloc(ifp);
if_attach(ifp);
if_alloc_sadl(ifp);
error = 0;
NET_LOCK();
+ sc->sc_dying = 1;
SLIST_REMOVE(&pflowif_list, sc, pflow_softc, sc_next);
NET_UNLOCK();
struct pflowreq pflowr;
int error;
+ if (sc->sc_dying)
+ return ENXIO;
+
switch (cmd) {
case SIOCSIFADDR:
case SIOCSIFDSTADDR:
case SIOCSIFFLAGS:
+ /* XXXSMP: enforce lock order */
+ NET_UNLOCK();
+ rw_enter_read(&sc->sc_lock);
+ NET_LOCK();
if ((ifp->if_flags & IFF_UP) && sc->so != NULL) {
ifp->if_flags |= IFF_RUNNING;
sc->sc_gcounter=pflowstats.pflow_flows;
pflow_sendout_ipfix_tmpl(sc);
} else
ifp->if_flags &= ~IFF_RUNNING;
+ rw_exit_read(&sc->sc_lock);
break;
case SIOCSIFMTU:
if (ifr->ifr_mtu < PFLOW_MINMTU)
/* XXXSMP breaks atomicity */
NET_UNLOCK();
+ rw_enter_write(&sc->sc_lock);
error = pflow_set(sc, &pflowr);
NET_LOCK();
- if (error != 0)
+ if (error != 0) {
+ rw_exit_write(&sc->sc_lock);
return (error);
+ }
if ((ifp->if_flags & IFF_UP) && sc->so != NULL) {
ifp->if_flags |= IFF_RUNNING;
pflow_sendout_ipfix_tmpl(sc);
} else
ifp->if_flags &= ~IFF_RUNNING;
+ rw_exit_write(&sc->sc_lock);
break;
int
pflow_sendout_mbuf(struct pflow_softc *sc, struct mbuf *m)
{
- sc->sc_if.if_opackets++;
- sc->sc_if.if_obytes += m->m_pkthdr.len;
+ counters_pkt(sc->sc_if.if_counters,
+ ifc_opackets, ifc_obytes, m->m_pkthdr.len);
if (sc->so == NULL) {
m_freem(m);
-/* $OpenBSD: if_pflow.h,v 1.18 2022/08/12 16:38:50 mvs Exp $ */
+/* $OpenBSD: if_pflow.h,v 1.19 2022/11/23 15:12:27 mvs Exp $ */
/*
* Copyright (c) 2008 Henning Brauer <henning@openbsd.org>
#ifdef _KERNEL
+/*
+ * Locks used to protect struct members and global data
+ * N net lock
+ * p this pflow_softc' `sc_lock'
+ */
+
struct pflow_softc {
+ struct rwlock sc_lock;
+
+ int sc_dying; /* [N] */
struct ifnet sc_if;
unsigned int sc_count;
struct timeout sc_tmo_tmpl;
struct mbuf_queue sc_outputqueue;
struct task sc_outputtask;
- struct socket *so;
+ struct socket *so; /* [p] */
struct mbuf *send_nam;
struct sockaddr *sc_flowsrc;
struct sockaddr *sc_flowdst;