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 *);