diff --git a/sys/net/if_vxlan.c b/sys/net/if_vxlan.c --- a/sys/net/if_vxlan.c +++ b/sys/net/if_vxlan.c @@ -160,6 +160,7 @@ struct vxlan_softc { struct ifnet *vxl_ifp; + struct vnet *vxl_orig_vnet; int vxl_reqcap; u_int vxl_fibnum; struct vxlan_socket *vxl_sock; @@ -1920,6 +1921,10 @@ ifp = sc->vxl_ifp; + /* We can't (dis)connect from a different vnet, so deny that. */ + if (sc->vxl_orig_vnet != curvnet) + return (0); + if (ifp->if_flags & IFF_UP) { if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) vxlan_init(sc); @@ -1931,6 +1936,21 @@ return (0); } +static void +vxlan_reassign(if_t ifp, struct vnet *new_vnet, char *unused __unused) +{ + struct vxlan_softc *sc = if_getsoftc(ifp); + + /* If we're leaving our home vnet. */ + if (curvnet == sc->vxl_orig_vnet) { + /* + * Set the interface up, because we won't be able to do + * so in the new vnet. + */ + vxlan_init(sc); + } +} + static int vxlan_ctrl_get_config(struct vxlan_softc *sc, void *arg) { @@ -2613,7 +2633,12 @@ } } else ro = NULL; + + /* The socket's vnet might not be our vnet. */ + MPASS(sc->vxl_orig_vnet == sc->vxl_sock->vxlso_sock->so_vnet); + CURVNET_SET(sc->vxl_orig_vnet); error = ip_output(m, NULL, ro, 0, sc->vxl_im4o, NULL); + CURVNET_RESTORE(); if (error == 0) { if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); if_inc_counter(ifp, IFCOUNTER_OBYTES, plen); @@ -2730,7 +2755,12 @@ m->m_pkthdr.csum_flags = CSUM_UDP_IPV6; m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum); } + + /* The socket's vnet might not be our vnet. */ + MPASS(sc->vxl_orig_vnet == sc->vxl_sock->vxlso_sock->so_vnet); + CURVNET_SET(sc->vxl_orig_vnet); error = ip6_output(m, NULL, ro, 0, sc->vxl_im6o, NULL, NULL); + CURVNET_RESTORE(); if (error == 0) { if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); if_inc_counter(ifp, IFCOUNTER_OBYTES, plen); @@ -3235,6 +3265,7 @@ vxlan_stats_alloc(sc); ifp = if_alloc(IFT_ETHER); sc->vxl_ifp = ifp; + sc->vxl_orig_vnet = curvnet; rm_init(&sc->vxl_lock, "vxlanrm"); callout_init_rw(&sc->vxl_callout, &sc->vxl_lock, 0); sc->vxl_port_hash_key = arc4random(); @@ -3266,6 +3297,9 @@ ether_gen_addr(ifp, &sc->vxl_hwaddr); ether_ifattach(ifp, sc->vxl_hwaddr.octet); + /* After ether_ifattach which sets ether_reassign(). */ + ifp->if_reassign = vxlan_reassign; + ifp->if_baudrate = 0; VXLAN_WLOCK(sc);