summaryrefslogtreecommitdiffstats
path: root/sys/net
diff options
context:
space:
mode:
authorzec <zec@FreeBSD.org>2010-08-13 18:17:32 +0000
committerzec <zec@FreeBSD.org>2010-08-13 18:17:32 +0000
commite1e5264fc5b1c858398b16deaf676b4c080ff9f1 (patch)
tree3c3d696aa7ddc5708c9c525a079af6624945d7b4 /sys/net
parentaf324b1be078ccd5569e29a9f568c9dada7b9650 (diff)
downloadFreeBSD-src-e1e5264fc5b1c858398b16deaf676b4c080ff9f1.zip
FreeBSD-src-e1e5264fc5b1c858398b16deaf676b4c080ff9f1.tar.gz
When moving an ethernet ifnet from one vnet to another, destroy the
associated ng_ether netgraph node in the current vnet, and create a new one in the target vnet. Reviewed by: julian MFC after: 3 days
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/if.c9
-rw-r--r--sys/net/if_ethersubr.c25
2 files changed, 34 insertions, 0 deletions
diff --git a/sys/net/if.c b/sys/net/if.c
index c1c6ee9..c387dbf 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -956,12 +956,21 @@ if_vmove(struct ifnet *ifp, struct vnet *new_vnet)
*/
IFNET_WLOCK();
ifindex_free_locked(ifp->if_index);
+ IFNET_WUNLOCK();
+
+ /*
+ * Perform interface-specific reassignment tasks, if provided by
+ * the driver.
+ */
+ if (ifp->if_reassign != NULL)
+ ifp->if_reassign(ifp, new_vnet, NULL);
/*
* Switch to the context of the target vnet.
*/
CURVNET_SET_QUIET(new_vnet);
+ IFNET_WLOCK();
if (ifindex_alloc_locked(&idx) != 0) {
IFNET_WUNLOCK();
panic("if_index overflow");
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c
index d284d11..5e5a548 100644
--- a/sys/net/if_ethersubr.c
+++ b/sys/net/if_ethersubr.c
@@ -129,6 +129,9 @@ 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
/* XXX: should be in an arp support file, not here */
MALLOC_DEFINE(M_ARPCOM, "arpcom", "802.* interface internals");
@@ -944,6 +947,9 @@ ether_ifattach(struct ifnet *ifp, const u_int8_t *lla)
ifp->if_output = ether_output;
ifp->if_input = ether_input;
ifp->if_resolvemulti = ether_resolvemulti;
+#ifdef VIMAGE
+ ifp->if_reassign = ether_reassign;
+#endif
if (ifp->if_baudrate == 0)
ifp->if_baudrate = IF_Mbps(10); /* just a default */
ifp->if_broadcastaddr = etherbroadcastaddr;
@@ -983,6 +989,25 @@ ether_ifdetach(struct ifnet *ifp)
if_detach(ifp);
}
+#ifdef VIMAGE
+void
+ether_reassign(struct ifnet *ifp, struct vnet *new_vnet, char *unused __unused)
+{
+
+ if (IFP2AC(ifp)->ac_netgraph != NULL) {
+ KASSERT(ng_ether_detach_p != NULL,
+ ("ng_ether_detach_p is NULL"));
+ (*ng_ether_detach_p)(ifp);
+ }
+
+ if (ng_ether_attach_p != NULL) {
+ CURVNET_SET_QUIET(new_vnet);
+ (*ng_ether_attach_p)(ifp);
+ CURVNET_RESTORE();
+ }
+}
+#endif
+
SYSCTL_DECL(_net_link);
SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW, 0, "Ethernet");
#if defined(INET) || defined(INET6)
OpenPOWER on IntegriCloud