pipex(4) has 2 mbuf queues: `pipexinq' and `pipexoutq'. When mbuf passed
to pipex it goes to one of these queues and pipexintr() will be
scheduled to process them. pipexintr() called from `netisr' context.

It's true for pppac(4) but for pppx(4) only incoming mbufs go to
`pipexinq. Outgoing mbufs go directly to stack. pppx(4) enabled in
npppd.conf(5) by default so I guess it's the common case of pipex(4)
usage.

The code looks like there is no requirements to this delayed mbufs
processing, we can pass it directly to stack as we do for pppx(4)
outgoing traffic.

Also we have some troubles with pipexintr() as it was described in [1].
It's protection of `ph_cookie'. We don't this protection this time and
we can't because we should brake if_get(9) logic.

Diff below removes pipexintr(). Now all mbufs passed directly without
enqueueing within pipex(4). We also can destroy sessions safe in all
cases. We also can use if_get(9) instead using unreferenced pointers to
`ifnet' within pipex(4). We also avoided context switch while we
processing mbufs within pipex(4). We decreased latency.

I'm seeding debian torrents with this diff an all goes well.

1. https://marc.info/?t=159300809000002&r=1&w=2

Index: lib/libc/sys/sysctl.2
===================================================================
RCS file: /cvs/src/lib/libc/sys/sysctl.2,v
retrieving revision 1.40
diff -u -p -r1.40 sysctl.2
--- lib/libc/sys/sysctl.2       17 May 2020 05:48:39 -0000      1.40
+++ lib/libc/sys/sysctl.2       1 Jul 2020 19:20:22 -0000
@@ -2033,35 +2033,11 @@ The currently defined variable names are
 .Bl -column "Third level name" "integer" "Changeable" -offset indent
 .It Sy "Third level name" Ta Sy "Type" Ta Sy "Changeable"
 .It Dv PIPEXCTL_ENABLE Ta integer Ta yes
-.It Dv PIPEXCTL_INQ Ta node Ta not applicable
-.It Dv PIPEXCTL_OUTQ Ta node Ta not applicable
 .El
 .Bl -tag -width "123456"
 .It Dv PIPEXCTL_ENABLE
 If set to 1, enable PIPEX processing.
 The default is 0.
-.It Dv PIPEXCTL_INQ Pq Va net.pipex.inq
-Fourth level comprises an array of
-.Vt struct ifqueue
-structures containing information about the PIPEX packet input queue.
-The forth level names for the elements of
-.Vt struct ifqueue
-are the same as described in
-.Li ip.arpq
-in the
-.Dv PF_INET
-section.
-.It Dv PIPEXCTL_OUTQ Pq Va net.pipex.outq
-Fourth level comprises an array of
-.Vt struct ifqueue
-structures containing information about PIPEX packet output queue.
-The forth level names for the elements of
-.Vt struct ifqueue
-are the same as described in
-.Li ip.arpq
-in the
-.Dv PF_INET
-section.
 .El
 .El
 .Ss CTL_VFS
Index: sys/net/if.c
===================================================================
RCS file: /cvs/src/sys/net/if.c,v
retrieving revision 1.611
diff -u -p -r1.611 if.c
--- sys/net/if.c        30 Jun 2020 09:31:38 -0000      1.611
+++ sys/net/if.c        1 Jul 2020 19:20:27 -0000
@@ -1012,13 +1012,6 @@ if_netisr(void *unused)
                        KERNEL_UNLOCK();
                }
 #endif
-#ifdef PIPEX
-               if (n & (1 << NETISR_PIPEX)) {
-                       KERNEL_LOCK();
-                       pipexintr();
-                       KERNEL_UNLOCK();
-               }
-#endif
                t |= n;
        }
 
Index: sys/net/netisr.h
===================================================================
RCS file: /cvs/src/sys/net/netisr.h,v
retrieving revision 1.51
diff -u -p -r1.51 netisr.h
--- sys/net/netisr.h    6 Aug 2019 22:57:54 -0000       1.51
+++ sys/net/netisr.h    1 Jul 2020 19:20:27 -0000
@@ -48,7 +48,6 @@
 #define        NETISR_IPV6     24              /* same as AF_INET6 */
 #define        NETISR_ISDN     26              /* same as AF_E164 */
 #define        NETISR_PPP      28              /* for PPP processing */
-#define        NETISR_PIPEX    27              /* for pipex processing */
 #define        NETISR_BRIDGE   29              /* for bridge processing */
 #define        NETISR_PPPOE    30              /* for pppoe processing */
 #define        NETISR_SWITCH   31              /* for switch dataplane */
@@ -68,7 +67,6 @@ void  bridgeintr(void);
 void   pppoeintr(void);
 void   switchintr(void);
 void   pfsyncintr(void);
-void   pipexintr(void);
 
 #define        schednetisr(anisr)                                              
\
 do {                                                                   \
Index: sys/net/pipex.c
===================================================================
RCS file: /cvs/src/sys/net/pipex.c,v
retrieving revision 1.117
diff -u -p -r1.117 pipex.c
--- sys/net/pipex.c     30 Jun 2020 14:05:13 -0000      1.117
+++ sys/net/pipex.c     1 Jul 2020 19:20:28 -0000
@@ -97,10 +97,6 @@ struct radix_node_head       *pipex_rd_head6 =
 struct timeout pipex_timer_ch;         /* callout timer context */
 int pipex_prune = 1;                   /* walk list every seconds */
 
-/* pipex traffic queue */
-struct mbuf_queue pipexinq = MBUF_QUEUE_INITIALIZER(IFQ_MAXLEN, IPL_NET);
-struct mbuf_queue pipexoutq = MBUF_QUEUE_INITIALIZER(IFQ_MAXLEN, IPL_NET);
-
 /* borrow an mbuf pkthdr field */
 #define ph_ppp_proto ether_vtag
 
@@ -713,82 +709,6 @@ pipex_lookup_by_session_id(int protocol,
 }
 
 /***********************************************************************
- * Queue and Software Interrupt Handler
- ***********************************************************************/
-void
-pipexintr(void)
-{
-       struct pipex_session *pkt_session;
-       u_int16_t proto;
-       struct mbuf *m;
-       struct mbuf_list ml;
-
-       /* ppp output */
-       mq_delist(&pipexoutq, &ml);
-       while ((m = ml_dequeue(&ml)) != NULL) {
-               pkt_session = m->m_pkthdr.ph_cookie;
-               if (pkt_session == NULL) {
-                       m_freem(m);
-                       continue;
-               }
-               proto = m->m_pkthdr.ph_ppp_proto;
-
-               m->m_pkthdr.ph_cookie = NULL;
-               m->m_pkthdr.ph_ppp_proto = 0;
-
-               if (pkt_session->is_multicast != 0) {
-                       struct pipex_session *session;
-                       struct mbuf *m0;
-
-                       LIST_FOREACH(session, &pipex_session_list,
-                           session_list) {
-                               if (session->pipex_iface !=
-                                   pkt_session->pipex_iface)
-                                       continue;
-                               if (session->ip_forward == 0 &&
-                                   session->ip6_forward == 0)
-                                       continue;
-                               m0 = m_copym(m, 0, M_COPYALL, M_NOWAIT);
-                               if (m0 == NULL) {
-                                       session->stat.oerrors++;
-                                       continue;
-                               }
-                               pipex_ppp_output(m0, session, proto);
-                       }
-                       m_freem(m);
-               } else
-                       pipex_ppp_output(m, pkt_session, proto);
-       }
-
-       /* ppp input */
-       mq_delist(&pipexinq, &ml);
-       while ((m = ml_dequeue(&ml)) != NULL) {
-               pkt_session = m->m_pkthdr.ph_cookie;
-               if (pkt_session == NULL) {
-                       m_freem(m);
-                       continue;
-               }
-               pipex_ppp_input(m, pkt_session, 0);
-       }
-}
-
-Static int
-pipex_ppp_enqueue(struct mbuf *m0, struct pipex_session *session,
-    struct mbuf_queue *mq)
-{
-       m0->m_pkthdr.ph_cookie = session;
-       /* XXX need to support other protocols */
-       m0->m_pkthdr.ph_ppp_proto = PPP_IP;
-
-       if (mq_enqueue(mq, m0) != 0)
-               return (1);
-
-       schednetisr(NETISR_PIPEX);
-
-       return (0);
-}
-
-/***********************************************************************
  * Timer functions
  ***********************************************************************/
 Static void
@@ -840,13 +760,6 @@ pipex_timer(void *ignored_arg)
                        /* FALLTHROUGH */
 
                case PIPEX_STATE_CLOSED:
-                       /*
-                        * mbuf queued in pipexinq or pipexoutq may have a
-                        * refererce to this session.
-                        */
-                       if (!mq_empty(&pipexinq) || !mq_empty(&pipexoutq))
-                               continue;
-
                        pipex_destroy_session(session);
                        break;
 
@@ -947,8 +860,26 @@ pipex_ip_output(struct mbuf *m0, struct 
                m0->m_flags &= ~(M_BCAST|M_MCAST);
 
        /* output ip packets to the session tunnel */
-       if (pipex_ppp_enqueue(m0, session, &pipexoutq))
-               goto dropped;
+       if (session->is_multicast != 0) {
+               struct pipex_session *session_tmp;
+               struct mbuf *m;
+
+               LIST_FOREACH(session_tmp, &pipex_session_list, session_list) {
+                       if (session->pipex_iface != session_tmp->pipex_iface)
+                               continue;
+                       if (session->ip_forward == 0 &&
+                           session->ip6_forward == 0)
+                               continue;
+                       m = m_copym(m0, 0, M_COPYALL, M_NOWAIT);
+                       if (m == NULL) {
+                               session->stat.oerrors++;
+                               continue;
+                       }
+                       pipex_ppp_output(m, session_tmp, PPP_IP);
+               }
+               m_freem(m);
+       } else
+               pipex_ppp_output(m0, session, PPP_IP);
 
        return;
 drop:
@@ -1207,7 +1138,7 @@ pipex_ip6_input(struct mbuf *m0, struct 
 
 Static struct mbuf *
 pipex_common_input(struct pipex_session *session, struct mbuf *m0, int hlen,
-    int plen, int useq)
+    int plen)
 {
        int proto, ppphlen;
        u_char code;
@@ -1255,19 +1186,10 @@ pipex_common_input(struct pipex_session 
                        m_adj(m0, plen - m0->m_pkthdr.len);
        }
 
-       if (!useq) {
-               pipex_ppp_input(m0, session, 0);
-               return (NULL);
-       }
-
-       /* input ppp packets to kernel session */
-       if (pipex_ppp_enqueue(m0, session, &pipexinq) != 0)
-               goto dropped;
-       else
-               return (NULL);
+       pipex_ppp_input(m0, session, 0);
+       return (NULL);
 drop:
        m_freem(m0);
-dropped:
        session->stat.ierrors++;
        return (NULL);
 
@@ -1363,7 +1285,7 @@ pipex_pppoe_input(struct mbuf *m0, struc
            sizeof(struct pipex_pppoe_header), (caddr_t)&pppoe);
 
        hlen = sizeof(struct ether_header) + sizeof(struct pipex_pppoe_header);
-       if ((m0 = pipex_common_input(session, m0, hlen, ntohs(pppoe.length), 0))
+       if ((m0 = pipex_common_input(session, m0, hlen, ntohs(pppoe.length)))
            == NULL)
                return (NULL);
        m_freem(m0);
@@ -1658,7 +1580,7 @@ pipex_pptp_input(struct mbuf *m0, struct
                        pipex_pptp_output(NULL, session, 0, 1);
        }
 
-       if ((m0 = pipex_common_input(session, m0, hlen, ntohs(gre->len), 1))
+       if ((m0 = pipex_common_input(session, m0, hlen, ntohs(gre->len)))
            == NULL) {
                /* ok,  The packet is for PIPEX */
                if (!rewind)
@@ -2092,7 +2014,7 @@ pipex_l2tp_input(struct mbuf *m0, int of
 
        length -= hlen + offset;
        hlen += off0 + offset;
-       if ((m0 = pipex_common_input(session, m0, hlen, length, 1)) == NULL) {
+       if ((m0 = pipex_common_input(session, m0, hlen, length)) == NULL) {
                /* ok,  The packet is for PIPEX */
                if (!rewind)
                        session->proto.l2tp.nr_gap += nseq;
@@ -3010,12 +2932,6 @@ pipex_sysctl(int *name, u_int namelen, v
                        return (ENOTDIR);
                return (sysctl_int(oldp, oldlenp, newp, newlen,
                    &pipex_enable));
-       case PIPEXCTL_INQ:
-               return (sysctl_mq(name + 1, namelen - 1,
-                   oldp, oldlenp, newp, newlen, &pipexinq));
-       case PIPEXCTL_OUTQ:
-               return (sysctl_mq(name + 1, namelen - 1,
-                   oldp, oldlenp, newp, newlen, &pipexoutq));
        default:
                return (ENOPROTOOPT);
        }
Index: sys/net/pipex.h
===================================================================
RCS file: /cvs/src/sys/net/pipex.h,v
retrieving revision 1.23
diff -u -p -r1.23 pipex.h
--- sys/net/pipex.h     5 Jun 2020 19:50:59 -0000       1.23
+++ sys/net/pipex.h     1 Jul 2020 19:20:28 -0000
@@ -33,15 +33,11 @@
  * Names for pipex sysctl objects
  */
 #define PIPEXCTL_ENABLE                1
-#define PIPEXCTL_INQ           2
-#define PIPEXCTL_OUTQ          3
-#define PIPEXCTL_MAXID         4
+#define PIPEXCTL_MAXID         2
 
 #define PIPEXCTL_NAMES { \
         { 0, 0 }, \
         { "enable", CTLTYPE_INT }, \
-        { "inq", CTLTYPE_NODE }, \
-        { "outq", CTLTYPE_NODE }, \
 }
 
 #define PIPEX_PROTO_L2TP               1       /* protocol L2TP */
Index: sys/net/pipex_local.h
===================================================================
RCS file: /cvs/src/sys/net/pipex_local.h,v
retrieving revision 1.35
diff -u -p -r1.35 pipex_local.h
--- sys/net/pipex_local.h       18 Jun 2020 14:20:12 -0000      1.35
+++ sys/net/pipex_local.h       1 Jul 2020 19:20:28 -0000
@@ -402,7 +402,8 @@ void                  pipex_ip_input (st
 #ifdef INET6
 void                  pipex_ip6_input (struct mbuf *, struct pipex_session *);
 #endif
-struct mbuf           *pipex_common_input(struct pipex_session *, struct mbuf 
*, int, int, int);
+struct mbuf           *pipex_common_input(struct pipex_session *,
+                          struct mbuf *, int, int);
 
 #ifdef PIPEX_PPPOE
 void                  pipex_pppoe_output (struct mbuf *, struct pipex_session 
*);

Reply via email to