diff options
author | zec <zec@FreeBSD.org> | 2010-08-13 18:17:32 +0000 |
---|---|---|
committer | zec <zec@FreeBSD.org> | 2010-08-13 18:17:32 +0000 |
commit | e1e5264fc5b1c858398b16deaf676b4c080ff9f1 (patch) | |
tree | 3c3d696aa7ddc5708c9c525a079af6624945d7b4 | |
parent | af324b1be078ccd5569e29a9f568c9dada7b9650 (diff) | |
download | FreeBSD-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
-rw-r--r-- | sys/net/if.c | 9 | ||||
-rw-r--r-- | sys/net/if_ethersubr.c | 25 |
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) |