This remove all but one splsoftnet() recursions when creating or
destroying cloned interfaces.

Note that I have to introduce some extra splsoftnet()/splx() dances in
tun(4) and tap(4) create functions.

ok?

Index: net/if.c
===================================================================
RCS file: /cvs/src/sys/net/if.c,v
retrieving revision 1.463
diff -u -p -r1.463 if.c
--- net/if.c    28 Nov 2016 11:18:02 -0000      1.463
+++ net/if.c    28 Nov 2016 14:16:03 -0000
@@ -133,6 +133,8 @@
 void   if_attachsetup(struct ifnet *);
 void   if_attachdomain(struct ifnet *);
 void   if_attach_common(struct ifnet *);
+int    if_setrdomain(struct ifnet *, int);
+void   if_slowtimo(void *);
 
 void   if_detached_start(struct ifnet *);
 int    if_detached_ioctl(struct ifnet *, u_long, caddr_t);
@@ -402,6 +404,8 @@ if_attachsetup(struct ifnet *ifp)
 {
        unsigned long ifidx;
 
+       splsoftassert(IPL_SOFTNET);
+
        TAILQ_INIT(&ifp->if_groups);
 
        if_addgroup(ifp, IFG_ALL);
@@ -501,17 +505,25 @@ if_attachdomain(struct ifnet *ifp)
 void
 if_attachhead(struct ifnet *ifp)
 {
+       int s;
+
+       s = splsoftnet();
        if_attach_common(ifp);
        TAILQ_INSERT_HEAD(&ifnet, ifp, if_list);
        if_attachsetup(ifp);
+       splx(s);
 }
 
 void
 if_attach(struct ifnet *ifp)
 {
+       int s;
+
+       s = splsoftnet();
        if_attach_common(ifp);
        TAILQ_INSERT_TAIL(&ifnet, ifp, if_list);
        if_attachsetup(ifp);
+       splx(s);
 }
 
 void
@@ -1036,7 +1048,9 @@ if_clone_create(const char *name, int rd
 {
        struct if_clone *ifc;
        struct ifnet *ifp;
-       int unit, ret, s;
+       int unit, ret;
+
+       splsoftassert(IPL_SOFTNET);
 
        ifc = if_clone_lookup(name, &unit);
        if (ifc == NULL)
@@ -1045,9 +1059,7 @@ if_clone_create(const char *name, int rd
        if (ifunit(name) != NULL)
                return (EEXIST);
 
-       s = splsoftnet();
        ret = (*ifc->ifc_create)(ifc, unit);
-       splx(s);
 
        if (ret != 0 || (ifp = ifunit(name)) == NULL)
                return (ret);
@@ -1067,7 +1079,8 @@ if_clone_destroy(const char *name)
 {
        struct if_clone *ifc;
        struct ifnet *ifp;
-       int error, s;
+
+       splsoftassert(IPL_SOFTNET);
 
        ifc = if_clone_lookup(name, NULL);
        if (ifc == NULL)
@@ -1081,15 +1094,13 @@ if_clone_destroy(const char *name)
                return (EOPNOTSUPP);
 
        if (ifp->if_flags & IFF_UP) {
+               int s;
                s = splnet();
                if_down(ifp);
                splx(s);
        }
 
-       s = splsoftnet();
-       error = (*ifc->ifc_destroy)(ifp);
-       splx(s);
-       return (error);
+       return ((*ifc->ifc_destroy)(ifp));
 }
 
 /*
@@ -1594,7 +1605,7 @@ int
 if_setrdomain(struct ifnet *ifp, int rdomain)
 {
        struct ifreq ifr;
-       int s, error;
+       int error;
 
        if (rdomain < 0 || rdomain > RT_TABLEID_MAX)
                return (EINVAL);
@@ -1618,11 +1629,8 @@ if_setrdomain(struct ifnet *ifp, int rdo
                if (error && (ifp != loifp || error != EEXIST))
                        return (error);
 
-
-               s = splsoftnet();
                if ((error = rtable_add(rdomain)) == 0)
                        rtable_l2set(rdomain, rdomain, loifp->if_index);
-               splx(s);
                if (error) {
                        if_clone_destroy(loifname);
                        return (error);
@@ -1638,6 +1646,8 @@ if_setrdomain(struct ifnet *ifp, int rdo
        /* remove all routing entries when switching domains */
        /* XXX this is a bit ugly */
        if (rdomain != ifp->if_rdomain) {
+               int s;
+
                s = splnet();
                /*
                 * We are tearing down the world.
Index: net/if.h
===================================================================
RCS file: /cvs/src/sys/net/if.h,v
retrieving revision 1.180
diff -u -p -r1.180 if.h
--- net/if.h    27 Oct 2016 03:00:35 -0000      1.180
+++ net/if.h    28 Nov 2016 14:16:03 -0000
@@ -467,7 +467,6 @@ void        if_detach(struct ifnet *);
 void   if_down(struct ifnet *);
 void   if_downall(void);
 void   if_link_state_change(struct ifnet *);
-void   if_slowtimo(void *);
 void   if_up(struct ifnet *);
 int    ifconf(u_long, caddr_t);
 void   ifinit(void);
@@ -485,7 +484,6 @@ void        if_congestion(void);
 int    if_congested(void);
 __dead void    unhandled_af(int);
 int    if_setlladdr(struct ifnet *, const uint8_t *);
-int    if_setrdomain(struct ifnet *, int);
 
 #endif /* _KERNEL */
 
Index: net/if_tun.c
===================================================================
RCS file: /cvs/src/sys/net/if_tun.c,v
retrieving revision 1.169
diff -u -p -r1.169 if_tun.c
--- net/if_tun.c        4 Sep 2016 15:46:39 -0000       1.169
+++ net/if_tun.c        28 Nov 2016 14:16:03 -0000
@@ -312,14 +312,17 @@ int
 tunopen(dev_t dev, int flag, int mode, struct proc *p)
 {
        struct tun_softc *tp;
-       int error;
+       unsigned int rdomain = rtable_l2(p->p_p->ps_rtableid);
 
        if ((tp = tun_lookup(minor(dev))) == NULL) {    /* create on demand */
                char    xname[IFNAMSIZ];
+               int     s, error;
 
                snprintf(xname, sizeof(xname), "%s%d", "tun", minor(dev));
-               if ((error = if_clone_create(xname,
-                   rtable_l2(p->p_p->ps_rtableid))) != 0)
+               s = splsoftnet();
+               error = if_clone_create(xname, rdomain);
+               splx(s);
+               if (error != 0)
                        return (error);
 
                if ((tp = tun_lookup(minor(dev))) == NULL)
@@ -334,14 +337,17 @@ int
 tapopen(dev_t dev, int flag, int mode, struct proc *p)
 {
        struct tun_softc *tp;
-       int error;
+       unsigned int rdomain = rtable_l2(p->p_p->ps_rtableid);
 
        if ((tp = tap_lookup(minor(dev))) == NULL) {    /* create on demand */
                char    xname[IFNAMSIZ];
+               int     s, error;
 
                snprintf(xname, sizeof(xname), "%s%d", "tap", minor(dev));
-               if ((error = if_clone_create(xname,
-                   rtable_l2(p->p_p->ps_rtableid))) != 0)
+               s = splsoftnet();
+               error = if_clone_create(xname, rdomain);
+               splx(s);
+               if (error != 0)
                        return (error);
 
                if ((tp = tap_lookup(minor(dev))) == NULL)
@@ -403,7 +409,7 @@ tapclose(dev_t dev, int flag, int mode, 
 int
 tun_dev_close(struct tun_softc *tp, int flag, int mode, struct proc *p)
 {
-       int                      s;
+       int                      s, error = 0;
        struct ifnet            *ifp;
 
        ifp = &tp->tun_if;
@@ -420,14 +426,16 @@ tun_dev_close(struct tun_softc *tp, int 
 
        TUNDEBUG(("%s: closed\n", ifp->if_xname));
 
-       if (!(tp->tun_flags & TUN_STAYUP))
-               return (if_clone_destroy(ifp->if_xname));
-       else {
+       if (!(tp->tun_flags & TUN_STAYUP)) {
+               s = splsoftnet();
+               error = if_clone_destroy(ifp->if_xname);
+               splx(s);
+       } else {
                tp->tun_pgid = 0;
                selwakeup(&tp->tun_rsel);
        }
 
-       return (0);
+       return (error);
 }
 
 int

Reply via email to