Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys Perform link state change processing on a work queue, ra...



details:   https://anonhg.NetBSD.org/src/rev/769be3541328
branches:  trunk
changeset: 1007107:769be3541328
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Thu Feb 06 23:30:19 2020 +0000

description:
Perform link state change processing on a work queue, rather than in a
softint.

diffstat:

 sys/net/if.c          |  69 +++++++++++++++++++++++++++++---------------------
 sys/net/if.h          |  10 +++++--
 sys/netinet/ip_carp.c |  12 ++------
 3 files changed, 50 insertions(+), 41 deletions(-)

diffs (266 lines):

diff -r 0d883dbf2621 -r 769be3541328 sys/net/if.c
--- a/sys/net/if.c      Thu Feb 06 22:52:25 2020 +0000
+++ b/sys/net/if.c      Thu Feb 06 23:30:19 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if.c,v 1.470 2020/02/01 12:54:50 riastradh Exp $       */
+/*     $NetBSD: if.c,v 1.471 2020/02/06 23:30:19 thorpej Exp $ */
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2008 The NetBSD Foundation, Inc.
@@ -90,7 +90,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.470 2020/02/01 12:54:50 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.471 2020/02/06 23:30:19 thorpej Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_inet.h"
@@ -180,6 +180,7 @@
 kmutex_t                       ifnet_mtx __cacheline_aligned;
 static struct psref_class      *ifnet_psref_class __read_mostly;
 static pserialize_t            ifnet_psz;
+static struct workqueue                *ifnet_link_state_wq __read_mostly;
 
 static kmutex_t                        if_clone_mtx;
 
@@ -211,7 +212,7 @@
 static int if_transmit(struct ifnet *, struct mbuf *);
 static int if_clone_create(const char *);
 static int if_clone_destroy(const char *);
-static void if_link_state_change_si(void *);
+static void if_link_state_change_work(struct work *, void *);
 static void if_up_locked(struct ifnet *);
 static void _if_down(struct ifnet *);
 static void if_down_deactivated(struct ifnet *);
@@ -298,6 +299,7 @@
 void
 ifinit1(void)
 {
+       int error __diagused;
 
 #ifdef NET_MPSAFE
        printf("NET_MPSAFE enabled\n");
@@ -310,6 +312,10 @@
        ifnet_psz = pserialize_create();
        ifnet_psref_class = psref_class_create("ifnet", IPL_SOFTNET);
        ifa_psref_class = psref_class_create("ifa", IPL_SOFTNET);
+       error = workqueue_create(&ifnet_link_state_wq, "iflnkst",
+           if_link_state_change_work, NULL, PRI_SOFTNET, IPL_SOFTNET,
+           WQ_MPSAFE);
+       KASSERT(error == 0);
        PSLIST_INIT(&ifnet_pslist);
 
        if_indexlim = 8;
@@ -717,17 +723,6 @@
 
        IF_AFDATA_LOCK_INIT(ifp);
 
-       if (if_is_link_state_changeable(ifp)) {
-               u_int flags = SOFTINT_NET;
-               flags |= if_is_mpsafe(ifp) ? SOFTINT_MPSAFE : 0;
-               ifp->if_link_si = softint_establish(flags,
-                   if_link_state_change_si, ifp);
-               if (ifp->if_link_si == NULL) {
-                       rv = ENOMEM;
-                       goto fail;
-               }
-       }
-
        PSLIST_ENTRY_INIT(ifp, if_pslist_entry);
        PSLIST_INIT(&ifp->if_addr_pslist);
        psref_target_init(&ifp->if_psref, ifnet_psref_class);
@@ -1484,11 +1479,6 @@
 
        IF_AFDATA_LOCK_DESTROY(ifp);
 
-       if (if_is_link_state_changeable(ifp)) {
-               softint_disestablish(ifp->if_link_si);
-               ifp->if_link_si = NULL;
-       }
-
        /*
         * remove packets that came from ifp, from software interrupt queues.
         */
@@ -2252,7 +2242,7 @@
  * - if IFEF_MPSAFE is enabled, if_snd isn't used and lock contentions on
  *   ifq_lock don't happen
  * - if IFEF_MPSAFE is disabled, there is no lock contention on ifq_lock
- *   because if_snd, if_link_state_change and if_link_state_change_softint
+ *   because if_snd, if_link_state_change and if_link_state_change_process
  *   are all called with KERNEL_LOCK
  */
 #define IF_LINK_STATE_CHANGE_LOCK(ifp)         \
@@ -2260,6 +2250,16 @@
 #define IF_LINK_STATE_CHANGE_UNLOCK(ifp)       \
        mutex_exit((ifp)->if_snd.ifq_lock)
 
+static void
+if_link_state_change_work_schedule(struct ifnet *ifp)
+{
+       if (ifp->if_link_cansched && !ifp->if_link_scheduled) {
+               ifp->if_link_scheduled = true;
+               workqueue_enqueue(ifnet_link_state_wq, &ifp->if_link_work,
+                   NULL);
+       }
+}
+
 /*
  * Handle a change in the interface link state and
  * queue notifications.
@@ -2328,7 +2328,7 @@
        } else
                LQ_STORE(ifp->if_link_queue, idx, (uint8_t)link_state);
 
-       softint_schedule(ifp->if_link_si);
+       if_link_state_change_work_schedule(ifp);
 
 out:
        IF_LINK_STATE_CHANGE_UNLOCK(ifp);
@@ -2337,8 +2337,8 @@
 /*
  * Handle interface link state change notifications.
  */
-void
-if_link_state_change_softint(struct ifnet *ifp, int link_state)
+static void
+if_link_state_change_process(struct ifnet *ifp, int link_state)
 {
        struct domain *dp;
        int s = splnet();
@@ -2409,32 +2409,34 @@
  * Process the interface link state change queue.
  */
 static void
-if_link_state_change_si(void *arg)
+if_link_state_change_work(struct work *work, void *arg)
 {
-       struct ifnet *ifp = arg;
+       struct ifnet *ifp = container_of(work, struct ifnet, if_link_work);
        int s;
        uint8_t state;
        bool schedule;
 
-       SOFTNET_KERNEL_LOCK_UNLESS_NET_MPSAFE();
+       KERNEL_LOCK_UNLESS_NET_MPSAFE();
        s = splnet();
 
        /* Pop a link state change from the queue and process it. */
        IF_LINK_STATE_CHANGE_LOCK(ifp);
+       ifp->if_link_scheduled = false;
        LQ_POP(ifp->if_link_queue, state);
        IF_LINK_STATE_CHANGE_UNLOCK(ifp);
 
-       if_link_state_change_softint(ifp, state);
+       if_link_state_change_process(ifp, state);
 
        /* If there is a link state change to come, schedule it. */
        IF_LINK_STATE_CHANGE_LOCK(ifp);
        schedule = (LQ_ITEM(ifp->if_link_queue, 0) != LINK_STATE_UNSET);
        IF_LINK_STATE_CHANGE_UNLOCK(ifp);
+
        if (schedule)
-               softint_schedule(ifp->if_link_si);
+               if_link_state_change_work_schedule(ifp);
 
        splx(s);
-       SOFTNET_KERNEL_UNLOCK_UNLESS_NET_MPSAFE();
+       KERNEL_UNLOCK_UNLESS_NET_MPSAFE();
 }
 
 /*
@@ -2517,6 +2519,11 @@
        pserialize_read_exit(s);
        curlwp_bindx(bound);
 
+       IF_LINK_STATE_CHANGE_LOCK(ifp);
+       ifp->if_link_cansched = false;
+       workqueue_wait(ifnet_link_state_wq, &ifp->if_link_work);
+       IF_LINK_STATE_CHANGE_UNLOCK(ifp);
+
        IFQ_PURGE(&ifp->if_snd);
 #if NCARP > 0
        if (ifp->if_carp)
@@ -2589,6 +2596,10 @@
                if (dp->dom_if_up)
                        dp->dom_if_up(ifp);
        }
+
+       IF_LINK_STATE_CHANGE_LOCK(ifp);
+       ifp->if_link_cansched = true;
+       IF_LINK_STATE_CHANGE_UNLOCK(ifp);
 }
 
 /*
diff -r 0d883dbf2621 -r 769be3541328 sys/net/if.h
--- a/sys/net/if.h      Thu Feb 06 22:52:25 2020 +0000
+++ b/sys/net/if.h      Thu Feb 06 23:30:19 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if.h,v 1.280 2020/02/01 21:59:39 thorpej Exp $ */
+/*     $NetBSD: if.h,v 1.281 2020/02/06 23:30:19 thorpej Exp $ */
 
 /*-
  * Copyright (c) 1999, 2000, 2001 The NetBSD Foundation, Inc.
@@ -229,6 +229,7 @@
 #include <sys/percpu.h>
 #include <sys/callout.h>
 #include <sys/rwlock.h>
+#include <sys/workqueue.h>
 
 #endif /* _KERNEL */
 
@@ -402,8 +403,12 @@
        struct krwlock  *if_afdata_lock;/* :: */
        struct if_percpuq
                        *if_percpuq;    /* :: we should remove it in the future */
-       void            *if_link_si;    /* :: softint to handle link state changes */
+       struct work     if_link_work;   /* q: linkage on link state work queue */
        uint16_t        if_link_queue;  /* q: masked link state change queue */
+                                       /* q: is link state work scheduled? */
+       bool            if_link_scheduled;
+                                       /* q: can link state work be scheduled? */
+       bool            if_link_cansched;
        struct pslist_entry
                        if_pslist_entry;/* i: */
        struct psref_target
@@ -1125,7 +1130,6 @@
 void   if_down(struct ifnet *);
 void   if_down_locked(struct ifnet *);
 void   if_link_state_change(struct ifnet *, int);
-void   if_link_state_change_softint(struct ifnet *, int);
 void   if_up(struct ifnet *);
 void   ifinit(void);
 void   ifinit1(void);
diff -r 0d883dbf2621 -r 769be3541328 sys/netinet/ip_carp.c
--- a/sys/netinet/ip_carp.c     Thu Feb 06 22:52:25 2020 +0000
+++ b/sys/netinet/ip_carp.c     Thu Feb 06 23:30:19 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ip_carp.c,v 1.109 2020/02/04 05:46:32 thorpej Exp $    */
+/*     $NetBSD: ip_carp.c,v 1.110 2020/02/06 23:30:20 thorpej Exp $    */
 /*     $OpenBSD: ip_carp.c,v 1.113 2005/11/04 08:11:54 mcbride Exp $   */
 
 /*
@@ -33,7 +33,7 @@
 #endif
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_carp.c,v 1.109 2020/02/04 05:46:32 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_carp.c,v 1.110 2020/02/06 23:30:20 thorpej Exp $");
 
 /*
  * TODO:
@@ -2265,13 +2265,7 @@
                             ? LINK_STATE_DOWN : LINK_STATE_UNKNOWN;
                break;
        }
-       /*
-        * The lock is needed to serialize a call of
-        * if_link_state_change_softint from here and a call from softint.
-        */
-       KERNEL_LOCK(1, NULL);
-       if_link_state_change_softint(&sc->sc_if, link_state);
-       KERNEL_UNLOCK_ONE(NULL);
+       if_link_state_change(&sc->sc_if, link_state);
 }
 
 void



Home | Main Index | Thread Index | Old Index