Index | Thread | Search

From:
David Gwynne <david@gwynne.id.au>
Subject:
pppoe transmit optimisation
To:
tech@openbsd.org
Date:
Wed, 14 May 2025 11:24:58 +1000

Download raw body.

Thread
this let's packets being sent out pppoe interfaces bypass queues and go
straight onto the underlying interface.

it's complementary to src/sys/net/if_pppoe.c r1.85 "let pppoe data
packets go through if_vinput instead of the pppoeinq", but where that
skipped a queue on the rx side, this diff does it on the tx side.

i don't use pppoe anymore, so i need someone to test this diff before i
can commiti it.

Index: if_pppoe.c
===================================================================
RCS file: /cvs/src/sys/net/if_pppoe.c,v
diff -u -p -r1.84 if_pppoe.c
--- if_pppoe.c	26 Jun 2024 01:40:49 -0000	1.84
+++ if_pppoe.c	12 May 2025 04:04:16 -0000
@@ -42,6 +42,7 @@
 #include <sys/socket.h>
 #include <sys/syslog.h>
 #include <sys/ioctl.h>
+#include <sys/percpu.h>
 #include <net/if.h>
 #include <net/if_var.h>
 #include <net/if_types.h>
@@ -156,6 +157,7 @@ static void pppoe_abort_connect(struct p
 static int  pppoe_ioctl(struct ifnet *, unsigned long, caddr_t);
 static void pppoe_tls(struct sppp *);
 static void pppoe_tlf(struct sppp *);
+static int  pppoe_enqueue(struct ifnet *, struct mbuf *);
 static void pppoe_start(struct ifnet *);
 
 /* internal timeout handling */
@@ -231,6 +233,7 @@ pppoe_clone_create(struct if_clone *ifc,
 	sc->sc_sppp.pp_flags |= PP_KEEPALIVE;		/* use LCP keepalive */
 	sc->sc_sppp.pp_framebytes = PPPOE_HEADERLEN;	/* framing added to ppp packets */
 	sc->sc_sppp.pp_if.if_ioctl = pppoe_ioctl;
+	sc->sc_sppp.pp_if.if_enqueue = pppoe_enqueue;
 	sc->sc_sppp.pp_if.if_start = pppoe_start;
 	sc->sc_sppp.pp_if.if_rtrequest = p2p_rtrequest;
 	sc->sc_sppp.pp_if.if_xflags = IFXF_CLONED;
@@ -246,6 +249,7 @@ pppoe_clone_create(struct if_clone *ifc,
 	if_attach(&sc->sc_sppp.pp_if);
 	if_alloc_sadl(&sc->sc_sppp.pp_if);
 	sppp_attach(&sc->sc_sppp.pp_if);
+	if_counters_alloc(&sc->sc_sppp.pp_if);
 #if NBPFILTER > 0
 	bpfattach(&sc->sc_sppp.pp_if.if_bpf, &sc->sc_sppp.pp_if, DLT_PPP_ETHER, 0);
 #endif
@@ -1389,13 +1393,55 @@ pppoe_tlf(struct sppp *sp)
 	timeout_add_msec(&sc->sc_timeout, 20);
 }
 
+int
+pppoe_transmit(struct pppoe_softc *sc, struct mbuf *m)
+{
+	size_t len;
+	uint8_t *p;
+
+	len = m->m_pkthdr.len;
+	M_PREPEND(m, PPPOE_HEADERLEN, M_DONTWAIT);
+	if (m == NULL)
+		return (ENOBUFS);
+
+	p = mtod(m, u_int8_t *);
+	PPPOE_ADD_HEADER(p, 0, sc->sc_session, len);
+
+#if NBPFILTER > 0
+	if (sc->sc_sppp.pp_if.if_bpf)
+		bpf_mtap(sc->sc_sppp.pp_if.if_bpf, m, BPF_DIRECTION_OUT);
+#endif
+
+	return (pppoe_output(sc, m));
+}
+
+int
+pppoe_enqueue(struct ifnet *ifp, struct mbuf *m)
+{
+	struct pppoe_softc *sc;
+	int error;
+
+	if (!ifq_is_priq(&ifp->if_snd))
+		return (if_enqueue_ifq(ifp, m));
+
+	sc = ifp->if_softc;
+	if (sc->sc_state < PPPOE_STATE_SESSION) {
+		m_freem(m);
+		return (ENETDOWN);
+	}
+
+	error = pppoe_transmit(sc, m);
+	if (error != 0)
+		counters_inc(ifp->if_counters, ifc_oerrors);
+
+	return (error);
+}
+
 static void
 pppoe_start(struct ifnet *ifp)
 {
 	struct pppoe_softc *sc = (void *)ifp;
 	struct mbuf *m;
-	size_t len;
-	u_int8_t *p;
 
 	if (sppp_isempty(ifp))
 		return;
@@ -1407,21 +1453,6 @@ pppoe_start(struct ifnet *ifp)
 	}
 
 	while ((m = sppp_dequeue(ifp)) != NULL) {
-		len = m->m_pkthdr.len;
-		M_PREPEND(m, PPPOE_HEADERLEN, M_DONTWAIT);
-		if (m == NULL) {
-			ifp->if_oerrors++;
-			continue;
-		}
-		p = mtod(m, u_int8_t *);
-		PPPOE_ADD_HEADER(p, 0, sc->sc_session, len);
-
-#if NBPFILTER > 0
-		if(sc->sc_sppp.pp_if.if_bpf)
-			bpf_mtap(sc->sc_sppp.pp_if.if_bpf, m,
-			    BPF_DIRECTION_OUT);
-#endif
-
-		pppoe_output(sc, m);
+		pppoe_transmit(sc, m);
 	}
 }