Hi,

If I understood your diff right, pipex(4) is also affected through:

ip_local()
   -> ip_deliver()
     -> (*pr_input)()
       -> gre_input()
         -> gre_input_key()
           -> gre_input_1()
             -> pipex_pptp_input()

> On 7 Jul 2021, at 00:05, Alexander Bluhm <alexander.bl...@gmx.net> wrote:
> 
> Hi,
> 
> Thank a lot to Hrvoje Popovski for testing my diff and to sashan@
> and dlg@ for fixing all the fallout in pf and pseudo drivers.
> 
> Are there any bugs left?  I think everything has been fixed.
> 
> To make progress I think it should be commited.  Then we get MP
> pressure on the network stack in real live.  This allows us to fix
> bugs, optimize, and unlock further.
> 
> Performance comarison is here:
> http://bluhm.genua.de/perform/results/2021-07-06T08:17:07Z/perform.html
> 
> I think the spreading of the results comes from the kernel lock
> around arp and neighbor discovery.  These should be relaxed carefully
> later.
> 
> Here you see that the CPUs are much more busy during forwarding:
> http://bluhm.genua.de/perform/results/2021-07-06T08:17:07Z/2021-07-06T00%3A00%3A00Z/btrace/ssh_perform%40lt13_iperf3_-c10.3.46.36_-P10_-t10-btrace-kstack.0.svg
> http://bluhm.genua.de/perform/results/2021-07-06T08:17:07Z/patch-sys-ip-multiqueue-arp-klock.0/btrace/ssh_perform%40lt13_iperf3_-c10.3.46.36_-P10_-t10-btrace-kstack.0.svg
> 
> ok to commit?
> 
> bluhm
> 
> Index: net/if.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/net/if.c,v
> retrieving revision 1.642
> diff -u -p -r1.642 if.c
> --- net/if.c  30 Jun 2021 13:23:33 -0000      1.642
> +++ net/if.c  6 Jul 2021 15:37:41 -0000
> @@ -238,7 +238,7 @@ int       ifq_congestion;
> 
> int            netisr;
> 
> -#define      NET_TASKQ       1
> +#define      NET_TASKQ       4
> struct taskq  *nettqmp[NET_TASKQ];
> 
> struct task if_input_task_locked = TASK_INITIALIZER(if_netisr, NULL);
> @@ -834,10 +834,10 @@ if_input_process(struct ifnet *ifp, stru
>        * to PF globals, pipex globals, unicast and multicast addresses
>        * lists and the socket layer.
>        */
> -     NET_LOCK();
> +     NET_RLOCK_IN_SOFTNET();
>       while ((m = ml_dequeue(ml)) != NULL)
>               (*ifp->if_input)(ifp, m);
> -     NET_UNLOCK();
> +     NET_RUNLOCK_IN_SOFTNET();
> }
> 
> void
> @@ -895,6 +895,12 @@ if_netisr(void *unused)
>                       KERNEL_UNLOCK();
>               }
> #endif
> +             if (n & (1 << NETISR_IP))
> +                     ipintr();
> +#ifdef INET6
> +             if (n & (1 << NETISR_IPV6))
> +                     ip6intr();
> +#endif
> #if NPPP > 0
>               if (n & (1 << NETISR_PPP)) {
>                       KERNEL_LOCK();
> @@ -3316,12 +3322,15 @@ unhandled_af(int af)
>  * globals aren't ready to be accessed by multiple threads in
>  * parallel.
>  */
> -int           nettaskqs = NET_TASKQ;
> +int           nettaskqs;
> 
> struct taskq *
> net_tq(unsigned int ifindex)
> {
>       struct taskq *t = NULL;
> +
> +     if (nettaskqs == 0)
> +             nettaskqs = min(NET_TASKQ, ncpus);
> 
>       t = nettqmp[ifindex % nettaskqs];
> 
> Index: net/if_ethersubr.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/net/if_ethersubr.c,v
> retrieving revision 1.274
> diff -u -p -r1.274 if_ethersubr.c
> --- net/if_ethersubr.c        7 Mar 2021 06:02:32 -0000       1.274
> +++ net/if_ethersubr.c        6 Jul 2021 15:37:47 -0000
> @@ -222,7 +222,10 @@ ether_resolve(struct ifnet *ifp, struct 
> 
>       switch (af) {
>       case AF_INET:
> +             KERNEL_LOCK();
> +             /* XXXSMP there is a MP race in arpresolve() */
>               error = arpresolve(ifp, rt, m, dst, eh->ether_dhost);
> +             KERNEL_UNLOCK();
>               if (error)
>                       return (error);
>               eh->ether_type = htons(ETHERTYPE_IP);
> @@ -245,7 +248,10 @@ ether_resolve(struct ifnet *ifp, struct 
>               break;
> #ifdef INET6
>       case AF_INET6:
> +             KERNEL_LOCK();
> +             /* XXXSMP there is a MP race in nd6_resolve() */
>               error = nd6_resolve(ifp, rt, m, dst, eh->ether_dhost);
> +             KERNEL_UNLOCK();
>               if (error)
>                       return (error);
>               eh->ether_type = htons(ETHERTYPE_IPV6);
> Index: net/ifq.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/net/ifq.c,v
> retrieving revision 1.43
> diff -u -p -r1.43 ifq.c
> --- net/ifq.c 20 Feb 2021 04:37:26 -0000      1.43
> +++ net/ifq.c 6 Jul 2021 15:37:13 -0000
> @@ -243,7 +243,7 @@ void
> ifq_init(struct ifqueue *ifq, struct ifnet *ifp, unsigned int idx)
> {
>       ifq->ifq_if = ifp;
> -     ifq->ifq_softnet = net_tq(ifp->if_index); /* + idx */
> +     ifq->ifq_softnet = net_tq(ifp->if_index + idx);
>       ifq->ifq_softc = NULL;
> 
>       mtx_init(&ifq->ifq_mtx, IPL_NET);
> @@ -617,7 +617,7 @@ void
> ifiq_init(struct ifiqueue *ifiq, struct ifnet *ifp, unsigned int idx)
> {
>       ifiq->ifiq_if = ifp;
> -     ifiq->ifiq_softnet = net_tq(ifp->if_index); /* + idx */
> +     ifiq->ifiq_softnet = net_tq(ifp->if_index + idx);
>       ifiq->ifiq_softc = NULL;
> 
>       mtx_init(&ifiq->ifiq_mtx, IPL_NET);
> Index: net/netisr.h
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/net/netisr.h,v
> retrieving revision 1.55
> diff -u -p -r1.55 netisr.h
> --- net/netisr.h      5 Jan 2021 20:43:36 -0000       1.55
> +++ net/netisr.h      6 Jul 2021 15:37:13 -0000
> @@ -41,8 +41,10 @@
>  * interrupt used for scheduling the network code to calls
>  * on the lowest level routine of each protocol.
>  */
> +#define      NETISR_IP       2               /* same as AF_INET */
> #define       NETISR_PFSYNC   5               /* for pfsync "immediate" tx */
> #define       NETISR_ARP      18              /* same as AF_LINK */
> +#define      NETISR_IPV6     24              /* same as AF_INET6 */
> #define       NETISR_PPP      28              /* for PPP processing */
> #define       NETISR_BRIDGE   29              /* for bridge processing */
> #define       NETISR_SWITCH   31              /* for switch dataplane */
> @@ -57,6 +59,8 @@ extern int  netisr;                 /* scheduling bits 
> extern struct task if_input_task_locked;
> 
> void  arpintr(void);
> +void ipintr(void);
> +void ip6intr(void);
> void  pppintr(void);
> void  bridgeintr(void);
> void  switchintr(void);
> Index: netinet/ip_input.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_input.c,v
> retrieving revision 1.363
> diff -u -p -r1.363 ip_input.c
> --- netinet/ip_input.c        21 Jun 2021 22:09:14 -0000      1.363
> +++ netinet/ip_input.c        6 Jul 2021 15:37:41 -0000
> @@ -130,6 +130,8 @@ const struct sysctl_bounded_args ipctl_v
>       { IPCTL_ARPDOWN, &arpt_down, 0, INT_MAX },
> };
> 
> +struct niqueue ipintrq = NIQUEUE_INITIALIZER(IPQ_MAXLEN, NETISR_IP);
> +
> struct pool ipqent_pool;
> struct pool ipq_pool;
> 
> @@ -143,6 +145,7 @@ static struct mbuf_queue  ipsendraw_mq;
> extern struct niqueue         arpinq;
> 
> int   ip_ours(struct mbuf **, int *, int, int);
> +int  ip_local(struct mbuf **, int *, int, int);
> int   ip_dooptions(struct mbuf *, struct ifnet *);
> int   in_ouraddr(struct mbuf *, struct ifnet *, struct rtentry **);
> 
> @@ -230,6 +233,43 @@ ip_init(void)
> }
> 
> /*
> + * Enqueue packet for local delivery.  Queuing is used as a boundary
> + * between the network layer (input/forward path) running with shared
> + * NET_RLOCK_IN_SOFTNET() and the transport layer needing it exclusively.
> + */
> +int
> +ip_ours(struct mbuf **mp, int *offp, int nxt, int af)
> +{
> +     /* We are already in a IPv4/IPv6 local deliver loop. */
> +     if (af != AF_UNSPEC)
> +             return ip_local(mp, offp, nxt, af);
> +
> +     niq_enqueue(&ipintrq, *mp);
> +     *mp = NULL;
> +     return IPPROTO_DONE;
> +}
> +
> +/*
> + * Dequeue and process locally delivered packets.
> + */
> +void
> +ipintr(void)
> +{
> +     struct mbuf *m;
> +     int off, nxt;
> +
> +     while ((m = niq_dequeue(&ipintrq)) != NULL) {
> +#ifdef DIAGNOSTIC
> +             if ((m->m_flags & M_PKTHDR) == 0)
> +                     panic("ipintr no HDR");
> +#endif
> +             off = 0;
> +             nxt = ip_local(&m, &off, IPPROTO_IPV4, AF_UNSPEC);
> +             KASSERT(nxt == IPPROTO_DONE);
> +     }
> +}
> +
> +/*
>  * IPv4 input routine.
>  *
>  * Checksum and byte swap header.  Process options. Forward or deliver.
> @@ -514,7 +554,7 @@ ip_input_if(struct mbuf **mp, int *offp,
>  * If fragmented try to reassemble.  Pass to next level.
>  */
> int
> -ip_ours(struct mbuf **mp, int *offp, int nxt, int af)
> +ip_local(struct mbuf **mp, int *offp, int nxt, int af)
> {
>       struct mbuf *m = *mp;
>       struct ip *ip = mtod(m, struct ip *);
> @@ -1665,7 +1705,8 @@ ip_sysctl(int *name, u_int namelen, void
>                   newlen));
> #endif
>       case IPCTL_IFQUEUE:
> -             return (EOPNOTSUPP);
> +             return (sysctl_niq(name + 1, namelen - 1,
> +                 oldp, oldlenp, newp, newlen, &ipintrq));
>       case IPCTL_ARPQUEUE:
>               return (sysctl_niq(name + 1, namelen - 1,
>                   oldp, oldlenp, newp, newlen, &arpinq));
> Index: netinet/ip_var.h
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_var.h,v
> retrieving revision 1.88
> diff -u -p -r1.88 ip_var.h
> --- netinet/ip_var.h  30 Mar 2021 08:37:11 -0000      1.88
> +++ netinet/ip_var.h  6 Jul 2021 15:37:13 -0000
> @@ -248,7 +248,6 @@ void       ip_stripoptions(struct mbuf *);
> int    ip_sysctl(int *, u_int, void *, size_t *, void *, size_t);
> void   ip_savecontrol(struct inpcb *, struct mbuf **, struct ip *,
>           struct mbuf *);
> -void  ipintr(void);
> int    ip_input_if(struct mbuf **, int *, int, int, struct ifnet *);
> int    ip_deliver(struct mbuf **, int *, int, int);
> void   ip_forward(struct mbuf *, struct ifnet *, struct rtentry *, int);
> Index: netinet6/ip6_input.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_input.c,v
> retrieving revision 1.237
> diff -u -p -r1.237 ip6_input.c
> --- netinet6/ip6_input.c      3 Jun 2021 04:47:54 -0000       1.237
> +++ netinet6/ip6_input.c      6 Jul 2021 15:37:41 -0000
> @@ -115,11 +115,14 @@
> #include <netinet/ip_carp.h>
> #endif
> 
> +struct niqueue ip6intrq = NIQUEUE_INITIALIZER(IPQ_MAXLEN, NETISR_IPV6);
> +
> struct cpumem *ip6counters;
> 
> uint8_t ip6_soiikey[IP6_SOIIKEY_LEN];
> 
> int ip6_ours(struct mbuf **, int *, int, int);
> +int ip6_local(struct mbuf **, int *, int, int);
> int ip6_check_rh0hdr(struct mbuf *, int *);
> int ip6_hbhchcheck(struct mbuf *, int *, int *, int *);
> int ip6_hopopts_input(u_int32_t *, u_int32_t *, struct mbuf **, int *);
> @@ -162,6 +165,43 @@ ip6_init(void)
>       ip6counters = counters_alloc(ip6s_ncounters);
> }
> 
> +/*
> + * Enqueue packet for local delivery.  Queuing is used as a boundary
> + * between the network layer (input/forward path) running with shared
> + * NET_RLOCK_IN_SOFTNET() and the transport layer needing it exclusively.
> + */
> +int
> +ip6_ours(struct mbuf **mp, int *offp, int nxt, int af)
> +{
> +     /* We are already in a IPv4/IPv6 local deliver loop. */
> +     if (af != AF_UNSPEC)
> +             return ip6_local(mp, offp, nxt, af);
> +
> +     niq_enqueue(&ip6intrq, *mp);
> +     *mp = NULL;
> +     return IPPROTO_DONE;
> +}
> +
> +/*
> + * Dequeue and process locally delivered packets.
> + */
> +void
> +ip6intr(void)
> +{
> +     struct mbuf *m;
> +     int off, nxt;
> +
> +     while ((m = niq_dequeue(&ip6intrq)) != NULL) {
> +#ifdef DIAGNOSTIC
> +             if ((m->m_flags & M_PKTHDR) == 0)
> +                     panic("ip6intr no HDR");
> +#endif
> +             off = 0;
> +             nxt = ip6_local(&m, &off, IPPROTO_IPV6, AF_UNSPEC);
> +             KASSERT(nxt == IPPROTO_DONE);
> +     }
> +}
> +
> void
> ipv6_input(struct ifnet *ifp, struct mbuf *m)
> {
> @@ -544,7 +584,7 @@ ip6_input_if(struct mbuf **mp, int *offp
> }
> 
> int
> -ip6_ours(struct mbuf **mp, int *offp, int nxt, int af)
> +ip6_local(struct mbuf **mp, int *offp, int nxt, int af)
> {
>       if (ip6_hbhchcheck(*mp, offp, &nxt, NULL))
>               return IPPROTO_DONE;
> @@ -1470,7 +1510,8 @@ ip6_sysctl(int *name, u_int namelen, voi
>               NET_UNLOCK();
>               return (error);
>       case IPV6CTL_IFQUEUE:
> -             return (EOPNOTSUPP);
> +             return (sysctl_niq(name + 1, namelen - 1,
> +                 oldp, oldlenp, newp, newlen, &ip6intrq));
>       case IPV6CTL_SOIIKEY:
>               return (ip6_sysctl_soiikey(oldp, oldlenp, newp, newlen));
>       default:
> 

Reply via email to