aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristof Provost <kp@FreeBSD.org>2021-02-21 20:20:32 +0000
committerKristof Provost <kp@FreeBSD.org>2021-02-23 12:54:07 +0000
commit38c0951386d82f4c51cf4e245253cdef18d2254a (patch)
tree357001c1e614f94c867495b6c7918ecb0dd6e080
parent89fa9c34d76bbf85cd7cda60c1868f5e3dba4ec7 (diff)
downloadsrc-38c0951386d82f4c51cf4e245253cdef18d2254a.tar.gz
src-38c0951386d82f4c51cf4e245253cdef18d2254a.zip
bridge: Remove members when assigned to a new vnet
When the bridge is moved to a different vnet we must remove all of its member interfaces (and span interfaces), because we don't know if those will be moved along with it. We don't want to hold references to interfaces not in our vnet. Reviewed by: donner@ MFC after: 1 week Sponsored by: Orange Business Services Differential Revision: https://reviews.freebsd.org/D28859
-rw-r--r--sys/net/ethernet.h4
-rw-r--r--sys/net/if_bridge.c25
-rw-r--r--sys/net/if_ethersubr.c3
3 files changed, 29 insertions, 3 deletions
diff --git a/sys/net/ethernet.h b/sys/net/ethernet.h
index 38c0aa249272..f174ca9eb143 100644
--- a/sys/net/ethernet.h
+++ b/sys/net/ethernet.h
@@ -437,6 +437,10 @@ extern uint32_t ether_crc32_be(const uint8_t *, size_t);
extern void ether_demux(struct ifnet *, struct mbuf *);
extern void ether_ifattach(struct ifnet *, const u_int8_t *);
extern void ether_ifdetach(struct ifnet *);
+#ifdef VIMAGE
+struct vnet;
+extern void ether_reassign(struct ifnet *, struct vnet *, char *);
+#endif
extern int ether_ioctl(struct ifnet *, u_long, caddr_t);
extern int ether_output(struct ifnet *, struct mbuf *,
const struct sockaddr *, struct route *);
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
index 3dba672aa0fe..3e6b5ba8e0c2 100644
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -670,6 +670,28 @@ SYSCTL_PROC(_net_link_bridge, OID_AUTO, ipfw,
&VNET_NAME(pfil_ipfw), 0, &sysctl_pfil_ipfw, "I",
"Layer2 filter with IPFW");
+#ifdef VIMAGE
+static void
+bridge_reassign(struct ifnet *ifp, struct vnet *newvnet, char *arg)
+{
+ struct bridge_softc *sc = ifp->if_softc;
+ struct bridge_iflist *bif;
+
+ BRIDGE_LOCK(sc);
+
+ while ((bif = CK_LIST_FIRST(&sc->sc_iflist)) != NULL)
+ bridge_delete_member(sc, bif, 0);
+
+ while ((bif = CK_LIST_FIRST(&sc->sc_spanlist)) != NULL) {
+ bridge_delete_span(sc, bif);
+ }
+
+ BRIDGE_UNLOCK(sc);
+
+ ether_reassign(ifp, newvnet, arg);
+}
+#endif
+
/*
* bridge_clone_create:
*
@@ -716,6 +738,9 @@ bridge_clone_create(struct if_clone *ifc, int unit, caddr_t params)
/* Now undo some of the damage... */
ifp->if_baudrate = 0;
ifp->if_type = IFT_BRIDGE;
+#ifdef VIMAGE
+ ifp->if_reassign = bridge_reassign;
+#endif
BRIDGE_LIST_LOCK();
LIST_INSERT_HEAD(&V_bridge_list, sc, sc_list);
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c
index 77c138d7a092..01c2d2f7b3e8 100644
--- a/sys/net/if_ethersubr.c
+++ b/sys/net/if_ethersubr.c
@@ -117,9 +117,6 @@ static const u_char etherbroadcastaddr[ETHER_ADDR_LEN] =
static int ether_resolvemulti(struct ifnet *, struct sockaddr **,
struct sockaddr *);
-#ifdef VIMAGE
-static void ether_reassign(struct ifnet *, struct vnet *, char *);
-#endif
static int ether_requestencap(struct ifnet *, struct if_encap_req *);
#define senderr(e) do { error = (e); goto bad;} while (0)