Page MenuHomeFreeBSD

D36651.id110814.diff
No OneTemporary

D36651.id110814.diff

diff --git a/sys/net/if.c b/sys/net/if.c
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -708,7 +708,6 @@
bool
if_try_ref(struct ifnet *ifp)
{
- NET_EPOCH_ASSERT();
return (refcount_acquire_if_not_zero(&ifp->if_refcount));
}
@@ -1360,6 +1359,14 @@
}
CURVNET_RESTORE();
+ error = ifc_vmove(ifp, pr->pr_vnet, NULL);
+ if (error != ENOTSUP) {
+ sx_xunlock(&ifnet_detach_sxlock);
+ CURVNET_RESTORE();
+ prison_free(pr);
+ return (error);
+ }
+
found = if_unlink_ifnet(ifp, true);
if (! found) {
sx_xunlock(&ifnet_detach_sxlock);
@@ -1424,6 +1431,13 @@
return (EBUSY);
}
+ error = ifc_vmove(ifp, vnet_dst, NULL);
+ if (error != ENOTSUP) {
+ CURVNET_RESTORE();
+ prison_free(pr);
+ return (error);
+ }
+
/* Get interface back from child jail/vnet. */
found = if_unlink_ifnet(ifp, true);
MPASS(found);
diff --git a/sys/net/if_clone.h b/sys/net/if_clone.h
--- a/sys/net/if_clone.h
+++ b/sys/net/if_clone.h
@@ -56,6 +56,8 @@
typedef int ifc_create_f(struct if_clone *ifc, char *name, size_t maxlen,
struct ifc_data *ifd, struct ifnet **ifpp);
typedef int ifc_destroy_f(struct if_clone *ifc, struct ifnet *ifp, uint32_t flags);
+typedef int ifc_vmove_f(struct if_clone *ifc_src, struct ifnet *ifp_src,
+ struct ifc_data *ifd, struct if_clone *ifc_dst, struct ifnet **ifpp);
#define IFC_D_FORCE 0x10
struct if_clone_addreq {
@@ -66,15 +68,18 @@
ifc_match_f *match_f;
ifc_create_f *create_f;
ifc_destroy_f *destroy_f;
+ ifc_vmove_f *vmove_f;
};
#define IFC_C_NOGROUP 0x01
#define IFC_C_AUTOUNIT 0x02
#define IFC_NOGROUP IFC_C_NOGROUP
+#define IFC_C_NOMOVE 0x08
struct if_clone *ifc_attach_cloner(const char *name, struct if_clone_addreq *req);
void ifc_detach_cloner(struct if_clone *ifc);
int ifc_create_ifp(const char *name, struct ifc_data *ifd,
struct ifnet **ifpp);
+int ifc_vmove(struct ifnet *ifp, struct vnet *vnet, struct ifnet **ifpp);
int ifc_copyin(const struct ifc_data *ifd, void *target, size_t len);
#ifdef CLONE_COMPAT_13
diff --git a/sys/net/if_clone.c b/sys/net/if_clone.c
--- a/sys/net/if_clone.c
+++ b/sys/net/if_clone.c
@@ -75,6 +75,9 @@
ifc_match_f *ifc_match; /* (c) Matcher function */
ifc_create_f *ifc_create; /* (c) Creates new interface */
ifc_destroy_f *ifc_destroy; /* (c) Destroys cloned interface */
+#ifdef VIMAGE
+ ifc_vmove_f *ifc_vmove; /* (c) Moves between vnets */
+#endif
#ifdef CLONE_COMPAT_13
/* (c) Driver specific cloning functions. Called with no locks held. */
@@ -239,6 +242,93 @@
IF_CLONE_UNLOCK(ifc);
}
+#ifdef VIMAGE
+/*
+ * "Default" vmove handler deleting and re-creating interface
+ * without any creation params
+ */
+static int
+if_vmove_simple(struct if_clone *ifc_src, struct ifnet *ifp_src, struct ifc_data *ifd,
+ struct if_clone *ifc_dst, struct ifnet **ifpp)
+{
+ char ifname[IFNAMSIZ];
+ int error;
+
+ strlcpy(ifname, if_name(ifp_src), sizeof(ifname));
+ error = if_clone_destroyif(ifc_src, ifp_src);
+
+ if (error != 0)
+ return (error);
+
+ CURVNET_SET_QUIET(ifd->vnet);
+ error = if_clone_createif(ifc_dst, ifname, sizeof(ifname), ifd, ifpp);
+ CURVNET_RESTORE();
+
+ return (error);
+}
+
+static struct if_clone *
+ifc_find_cloner(const char *name, struct vnet *vnet)
+{
+ struct if_clone *ifc;
+
+ CURVNET_SET_QUIET(vnet);
+ IF_CLONERS_LOCK();
+ LIST_FOREACH(ifc, &V_if_cloners, ifc_list) {
+ if (strcmp(ifc->ifc_name, name) == 0) {
+ break;
+ }
+ }
+ IF_CLONERS_UNLOCK();
+ CURVNET_RESTORE();
+
+ return (ifc);
+}
+
+int
+ifc_vmove(struct ifnet *ifp, struct vnet *vnet,
+ struct ifnet **ifpp)
+{
+ struct ifnet *ifp_dst = NULL;
+ int error = 0;
+
+ if (!if_try_ref(ifp))
+ return (EINVAL);
+
+ struct if_clone *ifc_src = ifc_find_cloner(ifp->if_dname, ifp->if_vnet);
+
+ CURVNET_SET_QUIET(vnet);
+ bool found = ifunit(if_name(ifp)) != NULL;
+ struct if_clone *ifc_dst = ifc_find_cloner(ifp->if_dname, vnet);
+ printf("ifc_src=%p ifc_dst=%p\n", ifc_src, ifc_dst);
+
+ if (found)
+ error = EEXIST;
+ if (ifc_src == NULL || (ifc_src->ifc_flags & IFC_C_NOMOVE) ||
+ ifc_dst == NULL || (ifc_dst->ifc_flags & IFC_C_NOMOVE))
+ error = ENOTSUP;
+
+ if (error == 0) {
+ struct ifc_data ifd = { .vnet = vnet };
+ CURVNET_SET_QUIET(ifp->if_home_vnet);
+ error = ifc_src->ifc_vmove(ifc_src, ifp, &ifd, ifc_dst, &ifp_dst);
+ CURVNET_RESTORE();
+ }
+ if_rele(ifp);
+
+ if (error == 0)
+ if_clone_addif(ifc_dst, ifp_dst);
+ CURVNET_RESTORE();
+
+ printf("ifc_vmove: %p -> %p\n", ifp, ifp_dst);
+
+ if (ifpp != NULL)
+ *ifpp = ifp_dst;
+
+ return (error);
+}
+#endif
+
/*
* Create a clone network interface.
*/
@@ -282,16 +372,7 @@
if (ifp == NULL)
return (ENXIO);
- /* Find the cloner for this interface */
- CURVNET_SET_QUIET(ifp->if_home_vnet);
- IF_CLONERS_LOCK();
- LIST_FOREACH(ifc, &V_if_cloners, ifc_list) {
- if (strcmp(ifc->ifc_name, ifp->if_dname) == 0) {
- break;
- }
- }
- IF_CLONERS_UNLOCK();
- CURVNET_RESTORE();
+ ifc = ifc_find_cloner(ifp->if_dname, ifp->if_home_vnet);
if (ifc == NULL) {
if_rele(ifp);
return (EINVAL);
@@ -328,6 +409,7 @@
IF_CLONE_UNLOCK(ifc);
if (ifcifp == NULL) {
CURVNET_RESTORE();
+ printf("Iface %s not found in target vnet llist\n", if_name(ifp));
return (ENXIO); /* ifp is not on the list. */
}
if ((ifc->ifc_flags & IFC_C_NOGROUP) == 0)
@@ -401,10 +483,11 @@
return (NULL);
struct if_clone *ifc = if_clone_alloc(name, req->maxunit);
- ifc->ifc_match = req->match_f != NULL ? req->match_f : ifc_simple_match;
+ ifc->ifc_match = (req->match_f != NULL) ? req->match_f : ifc_simple_match;
ifc->ifc_create = req->create_f;
ifc->ifc_destroy = req->destroy_f;
- ifc->ifc_flags = (req->flags & (IFC_C_AUTOUNIT | IFC_C_NOGROUP));
+ ifc->ifc_vmove = (req->vmove_f != NULL) ? req->vmove_f : if_vmove_simple;
+ ifc->ifc_flags = (req->flags & (IFC_C_AUTOUNIT | IFC_C_NOGROUP | IFC_C_NOMOVE));
if (if_clone_attach(ifc) != 0)
return (NULL);
@@ -454,6 +537,7 @@
ifc->ifc_destroy = ifc_advanced_destroy_wrapper;
ifc->ifca_destroy = destroy;
ifc->ifca_create = create;
+ ifc->ifc_flags = IFC_C_NOMOVE;
if (if_clone_attach(ifc) != 0)
return (NULL);
@@ -500,7 +584,7 @@
ifc->ifcs_create = create;
ifc->ifcs_destroy = destroy;
ifc->ifcs_minifs = minifs;
- ifc->ifc_flags = IFC_C_AUTOUNIT;
+ ifc->ifc_flags = IFC_C_AUTOUNIT | IFC_C_NOMOVE;
if (if_clone_attach(ifc) != 0)
return (NULL);
diff --git a/sys/net/if_vlan.c b/sys/net/if_vlan.c
--- a/sys/net/if_vlan.c
+++ b/sys/net/if_vlan.c
@@ -326,6 +326,8 @@
static int vlan_clone_create(struct if_clone *, char *, size_t,
struct ifc_data *, struct ifnet **);
static int vlan_clone_destroy(struct if_clone *, struct ifnet *, uint32_t);
+static int vlan_clone_vmove(struct if_clone *, struct ifnet *,
+ struct ifc_data *, struct if_clone *, struct ifnet **);
static void vlan_ifdetach(void *arg, struct ifnet *ifp);
static void vlan_iflladdr(void *arg, struct ifnet *ifp);
@@ -903,6 +905,13 @@
/* For if_link_state_change() eyes only... */
extern void (*vlan_link_state_p)(struct ifnet *);
+static struct if_clone_addreq clone_req = {
+ .match_f = vlan_clone_match,
+ .create_f = vlan_clone_create,
+ .destroy_f = vlan_clone_destroy,
+ .vmove_f = vlan_clone_vmove,
+};
+
static int
vlan_modevent(module_t mod, int type, void *data)
{
@@ -932,12 +941,7 @@
vlan_pcp_p = vlan_pcp;
vlan_devat_p = vlan_devat;
#ifndef VIMAGE
- struct if_clone_addreq req = {
- .match_f = vlan_clone_match,
- .create_f = vlan_clone_create,
- .destroy_f = vlan_clone_destroy,
- };
- vlan_cloner = ifc_attach_cloner(vlanname, &req);
+ vlan_cloner = ifc_attach_cloner(vlanname, &clone_req);
#endif
if (bootverbose)
printf("vlan: initialized, using "
@@ -987,12 +991,7 @@
static void
vnet_vlan_init(const void *unused __unused)
{
- struct if_clone_addreq req = {
- .match_f = vlan_clone_match,
- .create_f = vlan_clone_create,
- .destroy_f = vlan_clone_destroy,
- };
- vlan_cloner = ifc_attach_cloner(vlanname, &req);
+ vlan_cloner = ifc_attach_cloner(vlanname, &clone_req);
V_vlan_cloner = vlan_cloner;
}
VNET_SYSINIT(vnet_vlan_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
@@ -1065,6 +1064,17 @@
return (1);
}
+struct vlanparams {
+ struct ifnet *parent;
+ int vid;
+ uint16_t proto;
+ uint8_t pcp;
+};
+
+static int
+vlan_create_specific(struct if_clone *ifc, char *name, int unit,
+ struct vlanparams *vp, struct ifnet **ifpp);
+
static int
vlan_clone_create(struct if_clone *ifc, char *name, size_t len,
struct ifc_data *ifd, struct ifnet **ifpp)
@@ -1076,13 +1086,8 @@
int error;
int vid = 0;
uint16_t proto = ETHERTYPE_VLAN;
- struct ifvlan *ifv;
- struct ifnet *ifp;
struct ifnet *p = NULL;
- struct ifaddr *ifa;
- struct sockaddr_dl *sdl;
struct vlanreq vlr;
- static const u_char eaddr[ETHER_ADDR_LEN]; /* 00:00:00:00:00:00 */
/*
@@ -1163,14 +1168,38 @@
}
}
+ struct vlanparams vp = {
+ .parent = p,
+ .vid = vid,
+ .proto = proto,
+ };
+
+ error = vlan_create_specific(ifc, name, unit, &vp, ifpp);
+ if (error != 0) {
+ if (!subinterface)
+ ifc_free_unit(ifc, unit);
+ }
+ if (p != NULL)
+ if_rele(p);
+
+ return (error);
+}
+
+static int
+vlan_create_specific(struct if_clone *ifc, char *name, int unit,
+ struct vlanparams *vp, struct ifnet **ifpp)
+{
+ struct ifvlan *ifv;
+ struct ifnet *ifp;
+ struct ifaddr *ifa;
+ struct sockaddr_dl *sdl;
+ static const u_char eaddr[ETHER_ADDR_LEN]; /* 00:00:00:00:00:00 */
+ int error;
+
ifv = malloc(sizeof(struct ifvlan), M_VLAN, M_WAITOK | M_ZERO);
ifp = ifv->ifv_ifp = if_alloc(IFT_ETHER);
if (ifp == NULL) {
- if (!subinterface)
- ifc_free_unit(ifc, unit);
free(ifv, M_VLAN);
- if (p != NULL)
- if_rele(p);
return (ENOSPC);
}
CK_SLIST_INIT(&ifv->vlan_mc_listhead);
@@ -1209,9 +1238,8 @@
sdl = (struct sockaddr_dl *)ifa->ifa_addr;
sdl->sdl_type = IFT_L2VLAN;
- if (p != NULL) {
- error = vlan_config(ifv, p, vid, proto);
- if_rele(p);
+ if (vp->parent != NULL) {
+ error = vlan_config(ifv, vp->parent, vp->vid, vp->proto);
if (error != 0) {
/*
* Since we've partially failed, we need to back
@@ -1221,8 +1249,6 @@
ether_ifdetach(ifp);
vlan_unconfig(ifp);
if_free(ifp);
- if (!subinterface)
- ifc_free_unit(ifc, unit);
free(ifv, M_VLAN);
return (error);
@@ -1262,6 +1288,52 @@
return (0);
}
+static int
+vlan_clone_vmove(struct if_clone *ifc_src, struct ifnet *ifp_src,
+ struct ifc_data *ifd, struct if_clone *ifc_dst, struct ifnet **ifpp)
+{
+ char ifname[IFNAMSIZ];
+ struct ifvlan *ifv;
+ int error, unit;
+
+ printf("vlanHERE\n");
+ VLAN_XLOCK();
+
+ /* Copy necessary data to re-create the interface */
+ ifv = ifp_src->if_softc;
+
+ struct vlanparams vp = {
+ .parent = (ifv->ifv_trunk != NULL) ? ifv->ifv_trunk->parent : NULL,
+ .vid = ifv->ifv_vid,
+ .proto = ifv->ifv_proto,
+ };
+ strlcpy(ifname, if_name(ifp_src), sizeof(ifname));
+ unit = ifp_src->if_dunit;
+ CURVNET_SET_QUIET(ifp_src->if_vnet);
+ error = if_clone_destroyif(ifc_src, ifp_src);
+ CURVNET_RESTORE();
+ printf("DESTROYING %s=%d\n", ifname, error);
+ VLAN_XUNLOCK();
+ ifp_src = NULL;
+
+ if (error == 0) {
+ CURVNET_SET_QUIET(ifd->vnet);
+ if (unit != IF_DUNIT_NONE)
+ error = ifc_alloc_unit(ifc_dst, &unit);
+ if (error == 0) {
+ VLAN_XLOCK();
+ error = vlan_create_specific(ifc_dst, ifname, unit, &vp, ifpp);
+ printf("CREATING %s = %d\n", ifname, error);
+ VLAN_XUNLOCK();
+ }
+ CURVNET_RESTORE();
+ }
+
+ printf("= cb end %d\n", error);
+
+ return (error);
+}
+
/*
* The ifp->if_init entry point for vlan(4) is a no-op.
*/
@@ -1523,7 +1595,7 @@
}
static int
-vlan_config(struct ifvlan *ifv, struct ifnet *p, uint16_t vid,
+vlan_config_locked(struct ifvlan *ifv, struct ifnet *p, uint16_t vid,
uint16_t proto)
{
struct epoch_tracker et;
@@ -1553,8 +1625,6 @@
if (trunk->parent != p)
return (EBUSY);
- VLAN_XLOCK();
-
ifv->ifv_proto = proto;
if (ifv->ifv_vid != vid) {
@@ -1563,11 +1633,9 @@
ifv->ifv_vid = vid;
error = vlan_inshash(trunk, ifv);
}
- /* Will unlock */
- goto done;
+ return (error);
}
- VLAN_XLOCK();
if (p->if_vlantrunk == NULL) {
trunk = malloc(sizeof(struct ifvlantrunk),
M_VLAN, M_WAITOK | M_ZERO);
@@ -1585,8 +1653,8 @@
ifv->ifv_vid = vid; /* must set this before vlan_inshash() */
ifv->ifv_pcp = 0; /* Default: best effort delivery. */
error = vlan_inshash(trunk, ifv);
- if (error)
- goto done;
+ if (error != 0)
+ return (error);
ifv->ifv_proto = proto;
ifv->ifv_encaplen = ETHER_VLAN_ENCAP_LEN;
ifv->ifv_mintu = ETHERMIN;
@@ -1681,7 +1749,15 @@
*/
(void)vlan_setmulti(ifp);
-done:
+ return (error);
+}
+
+static int
+vlan_config(struct ifvlan *ifv, struct ifnet *p, uint16_t vid,
+ uint16_t proto)
+{
+ VLAN_XLOCK();
+ int error = vlan_config_locked(ifv, p, vid, proto);
if (error == 0)
EVENTHANDLER_INVOKE(vlan_config, p, ifv->ifv_vid);
VLAN_XUNLOCK();

File Metadata

Mime Type
text/plain
Expires
Mon, Jul 27, 6:37 PM (3 h, 48 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35612615
Default Alt Text
D36651.id110814.diff (12 KB)

Event Timeline