Thank you very much.

I'll look at applying the diff but it's been a while since I've done it.

Brodey

On Sun, 1 Dec 2024 at 17:48, David Gwynne <da...@gwynne.id.au> wrote:

> 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