switch(4) is currently not handling device removal when the interface is
being destroyed.

Example:
# ifconfig switch0 up
# ifconfig vether0 up
# ifconfig switch0 add vether0
# ifconfig vether0 destroy # kernel panic here

This diff fixes it by calling the switch port detach on the right time.

ok?


Index: if.c
===================================================================
RCS file: /home/obsdcvs/src/sys/net/if.c,v
retrieving revision 1.450
diff -u -p -r1.450 if.c
--- if.c        22 Sep 2016 14:50:11 -0000      1.450
+++ if.c        26 Sep 2016 16:05:45 -0000
@@ -130,6 +130,10 @@
 #include <net/pfvar.h>
 #endif
 
+#if NSWITCH > 0
+#include <net/if_switch.h>
+#endif
+
 void   if_attachsetup(struct ifnet *);
 void   if_attachdomain(struct ifnet *);
 void   if_attach_common(struct ifnet *);
@@ -895,6 +899,11 @@ if_deactivate(struct ifnet *ifp)
        /* Remove the interface from any bridge it is part of.  */
        if (ifp->if_bridgeport)
                bridge_ifdetach(ifp);
+#endif
+
+#if NSWITCH > 0
+       if (ifp->if_switchport)
+               switch_port_detach(ifp);
 #endif
 
 #if NCARP > 0
Index: if_switch.c
===================================================================
RCS file: /home/obsdcvs/src/sys/net/if_switch.c,v
retrieving revision 1.5
diff -u -p -r1.5 if_switch.c
--- if_switch.c 4 Sep 2016 17:11:09 -0000       1.5
+++ if_switch.c 26 Sep 2016 16:08:17 -0000
@@ -629,6 +629,23 @@ done:
        return (error);
 }
 
+void
+switch_port_detach(struct ifnet *ifp)
+{
+       struct switch_softc     *sc = ifp->if_softc;
+       struct switch_port      *swpo;
+
+       swpo = (struct switch_port *)ifp->if_switchport;
+       if (swpo->swpo_flags & IFBIF_LOCAL)
+               switch_port_unset_local(sc, swpo);
+
+       ifp->if_switchport = NULL;
+       ifpromisc(ifp, 0);
+       if_ih_remove(ifp, switch_input, NULL);
+       TAILQ_REMOVE(&sc->sc_swpo_list, swpo, swpo_list_next);
+       free(swpo, M_DEVBUF, sizeof(*swpo));
+}
+
 int
 switch_port_del(struct switch_softc *sc, struct ifbreq *req)
 {
@@ -645,13 +662,7 @@ switch_port_del(struct switch_softc *sc,
        }
 
        if (swpo) {
-               if (swpo->swpo_flags & IFBIF_LOCAL)
-                       switch_port_unset_local(sc, swpo);
-               ifs->if_switchport = NULL;
-               ifpromisc(ifs, 0);
-               if_ih_remove(ifs, switch_input, NULL);
-               TAILQ_REMOVE(&sc->sc_swpo_list, swpo, swpo_list_next);
-               free(swpo, M_DEVBUF, sizeof(*swpo));
+               switch_port_detach(ifs);
                if_put(ifs);
                error = 0;
        } else
Index: if_switch.h
===================================================================
RCS file: /home/obsdcvs/src/sys/net/if_switch.h,v
retrieving revision 1.2
diff -u -p -r1.2 if_switch.h
--- if_switch.h 4 Sep 2016 16:47:41 -0000       1.2
+++ if_switch.h 26 Sep 2016 16:05:45 -0000
@@ -215,6 +215,7 @@ void         switch_port_egress(struct switch_s
 int     switch_swfcl_dup(struct switch_flow_classify *,
            struct switch_flow_classify *);
 void    switch_swfcl_free(struct switch_flow_classify *);
+void    switch_port_detach(struct ifnet *);
 
 /* switchctl.c */
 void    switch_dev_destroy(struct switch_softc *);

Reply via email to