On Wed, Nov 27, 2024 at 09:14:19AM -0500, Brodey Dover wrote:
> Thanks. The MTU is auto negotiated to 1492. max-mss is 1440 in pf.
> 
> I don't think OpenBSD has netisr or an equivalent since I don't see
> anything in the sysctl list, but it was implemented in FreeBSD and has
> allowed a number of people to fully saturate the mutli-gig symmetrical
> connections offered by newer ISPs using PPPoE. I should add *ON
> mutli-core/slower speed CPUs".

the diff below might improve pppoe rx performance.

> On Wed, 27 Nov 2024 at 03:03, Christer Solskogen <
> christer.solsko...@gmail.com> wrote:
> 
> > On Tue, Nov 26, 2024 at 10:59???PM Brodey Dover <dover...@gmail.com> wrote:
> > >
> > > So my modem is too buggy to do any DMZ work, thank you ISP.
> > >
> > > But the modem does pull 2375/2375. That???s down/up, which is why I was
> > thinking there was a serious bottleneck on the OBSD side.
> > >
> >
> > It's at least 20 years since I used PPPoE, but I seem to remember that
> > I had to lower the MTU to get the full speed. 1492 if I remember
> > correctly.
> >
> > --
> > chs

Index: if_ethersubr.c
===================================================================
RCS file: /cvs/src/sys/net/if_ethersubr.c,v
diff -u -p -r1.293 if_ethersubr.c
--- if_ethersubr.c      14 Feb 2024 22:41:48 -0000      1.293
+++ if_ethersubr.c      30 Nov 2024 06:29:47 -0000
@@ -561,7 +561,8 @@ ether_input(struct ifnet *ifp, struct mb
                        if (mq_enqueue(&pppoediscinq, m) == 0)
                                schednetisr(NETISR_PPPOE);
                } else {
-                       if (mq_enqueue(&pppoeinq, m) == 0)
+                       m = pppoe_vinput(ifp, m);
+                       if (m != NULL && mq_enqueue(&pppoeinq, m) == 0)
                                schednetisr(NETISR_PPPOE);
                }
                return;
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  30 Nov 2024 06:29:47 -0000
@@ -42,6 +42,8 @@
 #include <sys/socket.h>
 #include <sys/syslog.h>
 #include <sys/ioctl.h>
+#include <sys/smr.h>
+#include <sys/percpu.h>
 #include <net/if.h>
 #include <net/if_var.h>
 #include <net/if_types.h>
@@ -124,7 +126,9 @@ struct pppoe_softc {
        struct sppp sc_sppp;            /* contains a struct ifnet as first 
element */
        LIST_ENTRY(pppoe_softc) sc_list;/* [K] */
        unsigned int sc_eth_ifidx;      /* [K] */
+       caddr_t sc_bpf;
 
+       SMR_LIST_ENTRY(pppoe_softc) sc_session_entry; /* [K] */
        int sc_state;                   /* [K] discovery phase or session 
connected */
        struct ether_addr sc_dest;      /* [K] hardware address of concentrator 
*/
        u_int16_t sc_session;           /* [K] PPPoE session id */
@@ -175,6 +179,7 @@ static struct pppoe_softc *pppoe_find_so
 static struct mbuf       *pppoe_get_mbuf(size_t len);
 
 LIST_HEAD(pppoe_softc_head, pppoe_softc) pppoe_softc_list;
+SMR_LIST_HEAD(pppoe_softc_sessions, pppoe_softc) pppoe_sessions; /* [K] */
 
 /* interface cloning */
 int pppoe_clone_create(struct if_clone *, int);
@@ -209,9 +214,19 @@ void
 pppoeattach(int count)
 {
        LIST_INIT(&pppoe_softc_list);
+       SMR_LIST_INIT(&pppoe_sessions);
        if_clone_attach(&pppoe_cloner);
 }
 
+static void
+pppoe_set_state(struct pppoe_softc *sc, int state)
+{
+       KERNEL_ASSERT_LOCKED();
+       if (sc->sc_state == PPPOE_STATE_SESSION)
+               SMR_LIST_REMOVE_LOCKED(sc, sc_session_entry);
+       sc->sc_state = state;
+}
+
 /* Create a new interface. */
 int
 pppoe_clone_create(struct if_clone *ifc, int unit)
@@ -230,6 +245,8 @@ pppoe_clone_create(struct if_clone *ifc,
        sc->sc_sppp.pp_if.if_hdrlen = sizeof(struct ether_header) + 
PPPOE_HEADERLEN;
        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_input = p2p_input;
+       sc->sc_sppp.pp_if.if_bpf_mtap = p2p_bpf_mtap;
        sc->sc_sppp.pp_if.if_ioctl = pppoe_ioctl;
        sc->sc_sppp.pp_if.if_start = pppoe_start;
        sc->sc_sppp.pp_if.if_rtrequest = p2p_rtrequest;
@@ -243,11 +260,14 @@ pppoe_clone_create(struct if_clone *ifc,
        /* init timer for interface watchdog */
        timeout_set_proc(&sc->sc_timeout, pppoe_timeout, sc);
 
+       if_counters_alloc(&sc->sc_sppp.pp_if);
        if_attach(&sc->sc_sppp.pp_if);
        if_alloc_sadl(&sc->sc_sppp.pp_if);
        sppp_attach(&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);
+       bpfattach(&sc->sc_bpf, &sc->sc_sppp.pp_if, DLT_PPP_ETHER, 0);
+       bpfattach(&sc->sc_sppp.pp_if.if_bpf, &sc->sc_sppp.pp_if,
+           DLT_LOOP, sizeof(uint32_t));
 #endif
 
        NET_LOCK();
@@ -274,6 +294,7 @@ pppoe_clone_destroy(struct ifnet *ifp)
        NET_UNLOCK();
 
        timeout_del(&sc->sc_timeout);
+       pppoe_set_state(sc, PPPOE_STATE_INITIAL);
 
        sppp_detach(&sc->sc_sppp.pp_if);
        if_detach(ifp);
@@ -289,6 +310,8 @@ pppoe_clone_destroy(struct ifnet *ifp)
        if (sc->sc_relay_sid)
                free(sc->sc_relay_sid, M_DEVBUF, sc->sc_relay_sid_len);
 
+       smr_barrier();
+
        free(sc, M_DEVBUF, sizeof(*sc));
 
        return (0);
@@ -318,6 +341,28 @@ pppoe_find_softc_by_session(u_int sessio
        return (NULL);
 }
 
+static struct pppoe_softc *
+pppoe_smr_find_by_session(u_int session, u_int ifidx)
+{
+       struct pppoe_softc *sc;
+
+       if (session == 0)
+               return (NULL);
+
+       smr_read_enter();
+       SMR_LIST_FOREACH(sc, &pppoe_sessions, sc_session_entry) {
+               if (sc->sc_session == session &&
+                   sc->sc_eth_ifidx == ifidx) {
+                       /* XXX if_ref() */
+                       refcnt_take(&sc->sc_sppp.pp_if.if_refcnt);
+                       break;
+               }
+       }
+       smr_read_leave();
+
+       return (sc);
+}
+
 /*
  * Check host unique token passed and return appropriate softc pointer,
  * or NULL if token is bogus.
@@ -603,7 +648,7 @@ breakbreak:
 
                memcpy(&sc->sc_dest, eh->ether_shost, sizeof(sc->sc_dest));
                sc->sc_padr_retried = 0;
-               sc->sc_state = PPPOE_STATE_PADR_SENT;
+               pppoe_set_state(sc, PPPOE_STATE_PADR_SENT);
                if ((err = pppoe_send_padr(sc)) != 0) {
                        PPPOEDEBUG(("%s: failed to send PADR, error=%d\n",
                            sc->sc_sppp.pp_if.if_xname, err));
@@ -616,12 +661,16 @@ breakbreak:
                if (sc == NULL)
                        goto done;
 
+               KERNEL_ASSERT_LOCKED();
+
                sc->sc_session = session;
                timeout_del(&sc->sc_timeout);
                PPPOEDEBUG(("%s: session 0x%x connected\n",
                    sc->sc_sppp.pp_if.if_xname, session));
                sc->sc_state = PPPOE_STATE_SESSION;
                getmicrouptime(&sc->sc_session_time);
+               SMR_LIST_INSERT_HEAD_LOCKED(&pppoe_sessions, sc,
+                   sc_session_entry);
                sc->sc_sppp.pp_up(&sc->sc_sppp);        /* notify upper layers 
*/
 
                break;
@@ -635,7 +684,7 @@ breakbreak:
                    sc->sc_sppp.pp_if.if_xname, session));
 
                /* clean up softc */
-               sc->sc_state = PPPOE_STATE_INITIAL;
+               pppoe_set_state(sc, PPPOE_STATE_PADR_SENT);
                memcpy(&sc->sc_dest, etherbroadcastaddr, sizeof(sc->sc_dest));
                if (sc->sc_ac_cookie) {
                        free(sc->sc_ac_cookie, M_DEVBUF,
@@ -677,6 +726,108 @@ pppoe_disc_input(struct mbuf *m)
                m_freem(m);
 }
 
+struct mbuf *
+pppoe_vinput(struct ifnet *ifp0, struct mbuf *m)
+{
+       struct pppoe_softc *sc;
+       struct ifnet *ifp;
+       struct ether_header *eh;
+       struct pppoehdr *ph;
+       uint16_t proto;
+       int hlen = sizeof(*eh) + sizeof(*ph);
+       int phlen;
+       int plen;
+       int af = AF_UNSPEC;
+#if NBPFILTER > 0
+       caddr_t if_bpf;
+#endif
+       time_t now;
+
+       smr_read_enter();
+       sc = SMR_LIST_FIRST(&pppoe_sessions);
+       smr_read_leave();
+       if (sc == NULL)
+               return (m);
+
+       if (m->m_pkthdr.len < hlen)
+               return (m);
+       if (m->m_len < hlen) {
+               m = m_pullup(m, hlen);
+               if (m == NULL)
+                       return (NULL);
+       }
+
+       eh = mtod(m, struct ether_header *);
+       ph = (struct pppoehdr *)(eh + 1);
+       if (ph->vertype != PPPOE_VERTYPE)
+               return (m);
+       if (ph->code != 0)
+               return (m);
+
+       sc = pppoe_smr_find_by_session(ntohs(ph->session), ifp0->if_index);
+       if (sc == NULL) {
+               /* no session, don't waste any more time */
+               m_freem(m);
+               return (NULL);
+       }
+
+       ifp = &sc->sc_sppp.pp_if;
+
+       plen = ntohs(ph->plen);
+       if (plen < sizeof(proto))
+               goto drop;
+
+       phlen = hlen + sizeof(proto);
+       if (m->m_pkthdr.len < phlen)
+               goto drop;
+       if (m->m_len < phlen) {
+               m = m_pullup(m, phlen);
+               if (m == NULL)
+                       goto put;
+       }
+
+       proto = *(uint16_t *)(mtod(m, caddr_t) + hlen);
+       af = sppp_proto_up(ifp, proto);
+       if (af == AF_UNSPEC)
+               goto put;
+
+#if NBPFILTER > 0
+       if_bpf = sc->sc_bpf;
+       if (if_bpf) {
+               m_adj(m, sizeof(*eh));
+               bpf_mtap(sc->sc_bpf, m, BPF_DIRECTION_IN);
+               m_adj(m, phlen - sizeof(*eh));
+       } else
+#endif
+               m_adj(m, phlen);
+
+       plen -= sizeof(proto);
+       if (m->m_pkthdr.len < plen) {
+               counters_inc(ifp->if_counters, ifc_ierrors);
+               goto drop;
+       }
+
+       if (m->m_pkthdr.len > plen)
+               m_adj(m, plen - m->m_pkthdr.len);
+
+       /* XXX not 64bit or MP safe */
+       now = getuptime();
+       if (sc->sc_sppp.pp_last_activity < now)
+               sc->sc_sppp.pp_last_activity = now;
+
+       m->m_pkthdr.ph_family = af;
+       if_vinput(ifp, m);
+done:
+       m = NULL;
+put:
+       if_put(ifp);
+
+       return (m);
+drop:
+       m_freem(m);
+       goto done;
+}
+
 /* Input function for data packets */
 void
 pppoe_data_input(struct mbuf *m)
@@ -731,8 +882,8 @@ pppoe_data_input(struct mbuf *m)
        plen = ntohs(ph->plen);
 
 #if NBPFILTER > 0
-       if(sc->sc_sppp.pp_if.if_bpf)
-               bpf_mtap(sc->sc_sppp.pp_if.if_bpf, m, BPF_DIRECTION_IN);
+       if (sc->sc_bpf)
+               bpf_mtap(sc->sc_bpf, m, BPF_DIRECTION_IN);
 #endif
 
        m_adj(m, PPPOE_HEADERLEN);
@@ -927,7 +1078,7 @@ pppoe_ioctl(struct ifnet *ifp, unsigned 
                     && sc->sc_state >= PPPOE_STATE_PADI_SENT
                     && sc->sc_state < PPPOE_STATE_SESSION) {
                        timeout_del(&sc->sc_timeout);
-                       sc->sc_state = PPPOE_STATE_INITIAL;
+                       pppoe_set_state(sc, PPPOE_STATE_INITIAL);
                        sc->sc_padi_retried = 0;
                        sc->sc_padr_retried = 0;
                        memcpy(&sc->sc_dest, etherbroadcastaddr,
@@ -965,7 +1116,8 @@ pppoe_ioctl(struct ifnet *ifp, unsigned 
                                if (sc->sc_state >= PPPOE_STATE_PADI_SENT &&
                                    sc->sc_state < PPPOE_STATE_SESSION) {
                                        timeout_del(&sc->sc_timeout);
-                                       sc->sc_state = PPPOE_STATE_INITIAL;
+                                       pppoe_set_state(sc,
+                                           PPPOE_STATE_INITIAL);
                                        sc->sc_padi_retried = 0;
                                        sc->sc_padr_retried = 0;
                                        memcpy(&sc->sc_dest,
@@ -1136,7 +1288,7 @@ pppoe_timeout(void *arg)
                if (sc->sc_padr_retried >= PPPOE_DISC_MAXPADR) {
                        memcpy(&sc->sc_dest, etherbroadcastaddr,
                            sizeof(sc->sc_dest));
-                       sc->sc_state = PPPOE_STATE_PADI_SENT;
+                       pppoe_set_state(sc, PPPOE_STATE_PADI_SENT);
                        sc->sc_padr_retried = 0;
                        if ((err = pppoe_send_padi(sc)) != 0) {
                                PPPOEDEBUG(("%s: failed to send PADI, 
error=%d\n",
@@ -1179,7 +1331,7 @@ pppoe_connect(struct pppoe_softc *sc)
        x = splnet();
 
        /* save state, in case we fail to send PADI */
-       sc->sc_state = PPPOE_STATE_PADI_SENT;
+       pppoe_set_state(sc, PPPOE_STATE_PADI_SENT);
        sc->sc_padr_retried = 0;
        err = pppoe_send_padi(sc);
        if (err != 0)
@@ -1211,7 +1363,7 @@ pppoe_disconnect(struct pppoe_softc *sc)
        }
 
        /* cleanup softc */
-       sc->sc_state = PPPOE_STATE_INITIAL;
+       pppoe_set_state(sc, PPPOE_STATE_INITIAL);
        memcpy(&sc->sc_dest, etherbroadcastaddr, sizeof(sc->sc_dest));
        if (sc->sc_ac_cookie) {
                free(sc->sc_ac_cookie, M_DEVBUF, sc->sc_ac_cookie_len);
@@ -1239,14 +1391,14 @@ pppoe_abort_connect(struct pppoe_softc *
 {
        printf("%s: could not establish connection\n",
                sc->sc_sppp.pp_if.if_xname);
-       sc->sc_state = PPPOE_STATE_CLOSING;
+       pppoe_set_state(sc, PPPOE_STATE_CLOSING);
 
        /* notify upper layer */
        sc->sc_sppp.pp_down(&sc->sc_sppp);
 
        /* clear connection state */
        memcpy(&sc->sc_dest, etherbroadcastaddr, sizeof(sc->sc_dest));
-       sc->sc_state = PPPOE_STATE_INITIAL;
+       pppoe_set_state(sc, PPPOE_STATE_INITIAL);
 }
 
 /* Send a PADR packet */
@@ -1385,7 +1537,7 @@ pppoe_tlf(struct sppp *sp)
         * machine gets confused by this. We must return from this
         * function and defer disconnecting to the timeout handler.
         */
-       sc->sc_state = PPPOE_STATE_CLOSING;
+       pppoe_set_state(sc, PPPOE_STATE_CLOSING);
        timeout_add_msec(&sc->sc_timeout, 20);
 }
 
@@ -1417,9 +1569,8 @@ pppoe_start(struct ifnet *ifp)
                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);
+               if (sc->sc_bpf)
+                       bpf_mtap(sc->sc_bpf, m, BPF_DIRECTION_OUT);
 #endif
 
                pppoe_output(sc, m);
Index: if_pppoe.h
===================================================================
RCS file: /cvs/src/sys/net/if_pppoe.h,v
diff -u -p -r1.8 if_pppoe.h
--- if_pppoe.h  29 Jun 2022 09:08:07 -0000      1.8
+++ if_pppoe.h  30 Nov 2024 06:29:47 -0000
@@ -69,5 +69,8 @@ struct pppoeconnectionstate {
 extern struct mbuf_queue pppoediscinq;
 extern struct mbuf_queue pppoeinq;
 
+int             pppoe_if_exists(void);
+struct mbuf    *pppoe_vinput(struct ifnet *, struct mbuf *);
+
 #endif /* _KERNEL */
 #endif /* _NET_IF_PPPOE_H_ */
Index: if_sppp.h
===================================================================
RCS file: /cvs/src/sys/net/if_sppp.h,v
diff -u -p -r1.30 if_sppp.h
--- if_sppp.h   17 Nov 2021 18:00:24 -0000      1.30
+++ if_sppp.h   30 Nov 2024 06:29:47 -0000
@@ -232,6 +232,7 @@ struct sppp {
 void sppp_attach (struct ifnet *ifp);
 void sppp_detach (struct ifnet *ifp);
 void sppp_input (struct ifnet *ifp, struct mbuf *m);
+int sppp_proto_up(struct ifnet *ifp, uint16_t);
 
 /* Workaround */
 void spppattach (struct ifnet *ifp);
Index: if_spppsubr.c
===================================================================
RCS file: /cvs/src/sys/net/if_spppsubr.c,v
diff -u -p -r1.194 if_spppsubr.c
--- if_spppsubr.c       22 Jun 2024 10:22:29 -0000      1.194
+++ if_spppsubr.c       30 Nov 2024 06:29:47 -0000
@@ -415,6 +415,30 @@ spppattach(struct ifnet *ifp)
 {
 }
 
+int
+sppp_proto_up(struct ifnet *ifp, uint16_t proto)
+{
+       struct sppp *sp = (struct sppp *)ifp;
+       int af = AF_UNSPEC;
+
+       switch (ntohs(proto)) {
+       case PPP_IP:
+               if (sp->state[IDX_IPCP] == STATE_OPENED)
+                       af = AF_INET;
+               break;
+#ifdef INET6
+       case PPP_IPV6:
+               if (sp->state[IDX_IPV6CP] == STATE_OPENED)
+                       af = AF_INET6;
+               break;
+#endif
+       default:
+               break;
+       }
+
+       return (af);
+}
+
 /*
  * Process the received packet.
  */

Reply via email to