Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F163870471
D36651.id110814.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
12 KB
Referenced Files
None
Subscribers
None
D36651.id110814.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D36651: if_move: create new ifp instances on each vmove
Attached
Detach File
Event Timeline
Log In to Comment