Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F141979083
D54077.id167558.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
11 KB
Referenced Files
None
Subscribers
None
D54077.id167558.diff
View Options
diff --git a/sys/compat/linsysfs/linsysfs_net.c b/sys/compat/linsysfs/linsysfs_net.c
--- a/sys/compat/linsysfs/linsysfs_net.c
+++ b/sys/compat/linsysfs/linsysfs_net.c
@@ -90,7 +90,7 @@
CURVNET_SET(TD_TO_VNET(td));
NET_EPOCH_ENTER(et);
- ifp = ifname_linux_to_ifp(td, pn->pn_parent->pn_name);
+ ifp = ifname_linux_to_ifp(pn->pn_parent->pn_name);
if (ifp != NULL && (error = linux_ifhwaddr(ifp, &lsa)) == 0)
error = sbuf_printf(sb, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n",
lsa.sa_data[0], lsa.sa_data[1], lsa.sa_data[2],
@@ -119,7 +119,7 @@
CURVNET_SET(TD_TO_VNET(td));
NET_EPOCH_ENTER(et);
- ifp = ifname_linux_to_ifp(td, pn->pn_parent->pn_name);
+ ifp = ifname_linux_to_ifp(pn->pn_parent->pn_name);
if (ifp != NULL)
error = sbuf_printf(sb, "0x%x\n", linux_ifflags(ifp));
else
@@ -138,7 +138,7 @@
CURVNET_SET(TD_TO_VNET(td));
NET_EPOCH_ENTER(et);
- ifp = ifname_linux_to_ifp(td, pn->pn_parent->pn_name);
+ ifp = ifname_linux_to_ifp(pn->pn_parent->pn_name);
if (ifp != NULL)
error = sbuf_printf(sb, "%u\n", if_getindex(ifp));
else
@@ -157,7 +157,7 @@
CURVNET_SET(TD_TO_VNET(td));
NET_EPOCH_ENTER(et);
- ifp = ifname_linux_to_ifp(td, pn->pn_parent->pn_name);
+ ifp = ifname_linux_to_ifp( pn->pn_parent->pn_name);
if (ifp != NULL)
error = sbuf_printf(sb, "%u\n", if_getmtu(ifp));
else
@@ -186,7 +186,7 @@
CURVNET_SET(TD_TO_VNET(td));
NET_EPOCH_ENTER(et);
- ifp = ifname_linux_to_ifp(td, pn->pn_parent->pn_name);
+ ifp = ifname_linux_to_ifp(pn->pn_parent->pn_name);
if (ifp != NULL && (error = linux_ifhwaddr(ifp, &lsa)) == 0)
error = sbuf_printf(sb, "%d\n", lsa.sa_family);
else
@@ -207,7 +207,7 @@
visible = 0;
CURVNET_SET(TD_TO_VNET(td));
NET_EPOCH_ENTER(et);
- ifp = ifname_linux_to_ifp(td, pn->pn_name);
+ ifp = ifname_linux_to_ifp(pn->pn_name);
if (ifp != NULL) {
TAILQ_FOREACH_SAFE(nq, &ifp_nodes_q, ifp_nodes_next, nq_tmp) {
if (nq->ifp == ifp && nq->vnet == curvnet) {
diff --git a/sys/compat/linux/linux.h b/sys/compat/linux/linux.h
--- a/sys/compat/linux/linux.h
+++ b/sys/compat/linux/linux.h
@@ -359,6 +359,8 @@
ktrstruct("l_sigset_t", (s), l)
#endif
+void linux_ifnet_init(void);
+void linux_ifnet_uninit(void);
void linux_netlink_register(void);
void linux_netlink_deregister(void);
diff --git a/sys/compat/linux/linux_common.h b/sys/compat/linux/linux_common.h
--- a/sys/compat/linux/linux_common.h
+++ b/sys/compat/linux/linux_common.h
@@ -30,8 +30,7 @@
int ifname_bsd_to_linux_ifp(struct ifnet *, char *, size_t);
int ifname_bsd_to_linux_idx(u_int, char *, size_t);
-int ifname_bsd_to_linux_name(const char *, char *, size_t);
-struct ifnet *ifname_linux_to_ifp(struct thread *, const char *);
+struct ifnet *ifname_linux_to_ifp( const char *);
int ifname_linux_to_bsd(struct thread *, const char *, char *);
unsigned short linux_ifflags(struct ifnet *);
diff --git a/sys/compat/linux/linux_common.c b/sys/compat/linux/linux_common.c
--- a/sys/compat/linux/linux_common.c
+++ b/sys/compat/linux/linux_common.c
@@ -56,6 +56,7 @@
linux_osd_jail_register();
SET_FOREACH(ldhp, linux_device_handler_set)
linux_device_register_handler(*ldhp);
+ linux_ifnet_init();
linux_netlink_register();
break;
case MOD_UNLOAD:
@@ -63,6 +64,7 @@
linux_osd_jail_deregister();
SET_FOREACH(ldhp, linux_device_handler_set)
linux_device_unregister_handler(*ldhp);
+ linux_ifnet_uninit();
linux_netlink_deregister();
break;
default:
diff --git a/sys/compat/linux/linux_if.c b/sys/compat/linux/linux_if.c
--- a/sys/compat/linux/linux_if.c
+++ b/sys/compat/linux/linux_if.c
@@ -24,7 +24,9 @@
*/
#include <sys/param.h>
+#include <sys/systm.h>
#include <sys/ctype.h>
+#include <sys/eventhandler.h>
#include <sys/jail.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
@@ -32,6 +34,8 @@
#include <net/if_dl.h>
#include <net/if_types.h>
#include <net/if_var.h>
+#include <net/if_private.h>
+#include <net/vnet.h>
#include <compat/linux/linux.h>
#include <compat/linux/linux_common.h>
@@ -44,33 +48,74 @@
&use_real_ifnames, 0,
"Use FreeBSD interface names instead of generating ethN aliases");
-/*
- * Criteria for interface name translation
- */
-#define IFP_IS_ETH(ifp) (if_gettype(ifp) == IFT_ETHER)
-#define IFP_IS_LOOP(ifp) (if_gettype(ifp) == IFT_LOOP)
+VNET_DEFINE_STATIC(struct unrhdr *, linux_eth_unr);
+#define V_linux_eth_unr VNET(linux_eth_unr)
-/*
- * Translate a FreeBSD interface name to a Linux interface name
- * by interface name, and return the number of bytes copied to lxname.
- */
-int
-ifname_bsd_to_linux_name(const char *bsdname, char *lxname, size_t len)
+static eventhandler_tag ifnet_arrival_tag;
+static eventhandler_tag ifnet_departure_tag;
+
+static void
+linux_ifnet_arrival(void *arg __unused, struct ifnet *ifp)
{
- struct epoch_tracker et;
- struct ifnet *ifp;
- int ret;
+ if (ifp->if_type == IFT_ETHER)
+ ifp->if_linux_ethno = alloc_unr(V_linux_eth_unr);
+}
- CURVNET_ASSERT_SET();
+static void
+linux_ifnet_departure(void *arg __unused, struct ifnet *ifp)
+{
+ if (ifp->if_type == IFT_ETHER)
+ free_unr(V_linux_eth_unr, ifp->if_linux_ethno);
+}
- ret = 0;
+void
+linux_ifnet_init(void)
+{
+ ifnet_arrival_tag = EVENTHANDLER_REGISTER(ifnet_arrival_event,
+ linux_ifnet_arrival, NULL, EVENTHANDLER_PRI_FIRST);
+ ifnet_departure_tag = EVENTHANDLER_REGISTER(ifnet_departure_event,
+ linux_ifnet_departure, NULL, EVENTHANDLER_PRI_LAST);
+}
+
+void
+linux_ifnet_uninit(void)
+{
+ EVENTHANDLER_DEREGISTER(ifnet_arrival_event, ifnet_arrival_tag);
+ EVENTHANDLER_DEREGISTER(ifnet_departure_event, ifnet_departure_tag);
+}
+
+static void
+linux_ifnet_vnet_init(void *arg __unused)
+{
+ struct epoch_tracker et;
+ struct if_iter it;
+ if_t ifp;
+
+ V_linux_eth_unr = new_unrhdr(0, INT_MAX, NULL);
NET_EPOCH_ENTER(et);
- ifp = ifunit(bsdname);
- if (ifp != NULL)
- ret = ifname_bsd_to_linux_ifp(ifp, lxname, len);
+ for (ifp = if_iter_start(&it); ifp != NULL; ifp = if_iter_next(&it))
+ linux_ifnet_arrival(NULL, ifp);
NET_EPOCH_EXIT(et);
- return (ret);
}
+VNET_SYSINIT(linux_ifnet_vnet_init, SI_SUB_PROTO_IF, SI_ORDER_ANY,
+ linux_ifnet_vnet_init, NULL);
+
+#ifdef VIMAGE
+static void
+linux_ifnet_vnet_uninit(void *arg __unused)
+{
+ delete_unrhdr(V_linux_eth_unr);
+}
+VNET_SYSUNINIT(linux_ifnet_vnet_uninit, SI_SUB_PROTO_IF, SI_ORDER_ANY,
+ linux_ifnet_vnet_uninit, NULL);
+#endif
+
+
+/*
+ * Criteria for interface name translation
+ */
+#define IFP_IS_ETH(ifp) (if_gettype(ifp) == IFT_ETHER)
+#define IFP_IS_LOOP(ifp) (if_gettype(ifp) == IFT_LOOP)
/*
* Translate a FreeBSD interface name to a Linux interface name
@@ -99,37 +144,9 @@
* and return the number of bytes copied to lxname, 0 if interface
* not found, -1 on error.
*/
-struct ifname_bsd_to_linux_ifp_cb_s {
- struct ifnet *ifp;
- int ethno;
- char *lxname;
- size_t len;
-};
-
-static int
-ifname_bsd_to_linux_ifp_cb(if_t ifp, void *arg)
-{
- struct ifname_bsd_to_linux_ifp_cb_s *cbs = arg;
-
- if (ifp == cbs->ifp)
- return (snprintf(cbs->lxname, cbs->len, "eth%d", cbs->ethno));
- if (IFP_IS_ETH(ifp))
- cbs->ethno++;
- return (0);
-}
-
int
ifname_bsd_to_linux_ifp(struct ifnet *ifp, char *lxname, size_t len)
{
- struct ifname_bsd_to_linux_ifp_cb_s arg = {
- .ifp = ifp,
- .ethno = 0,
- .lxname = lxname,
- .len = len,
- };
-
- NET_EPOCH_ASSERT();
-
/*
* Linux loopback interface name is lo (not lo0),
* we translate lo to lo0, loX to loX.
@@ -142,7 +159,7 @@
return (strlcpy(lxname, if_name(ifp), len));
/* Determine the (relative) unit number for ethernet interfaces. */
- return (if_foreach(ifname_bsd_to_linux_ifp_cb, &arg));
+ return (snprintf(lxname, len, "eth%d", ifp->if_linux_ethno));
}
/*
@@ -154,7 +171,6 @@
struct ifname_linux_to_ifp_cb_s {
bool is_lo;
bool is_eth;
- int ethno;
int unit;
const char *lxname;
if_t ifp;
@@ -174,12 +190,10 @@
*/
if (strncmp(if_name(ifp), cbs->lxname, LINUX_IFNAMSIZ) == 0)
goto out;
- if (cbs->is_eth && IFP_IS_ETH(ifp) && cbs->unit == cbs->ethno)
+ if (cbs->is_eth && IFP_IS_ETH(ifp) && ifp->if_linux_ethno == cbs->unit)
goto out;
if (cbs->is_lo && IFP_IS_LOOP(ifp))
goto out;
- if (IFP_IS_ETH(ifp))
- cbs->ethno++;
return (0);
out:
@@ -188,12 +202,10 @@
}
struct ifnet *
-ifname_linux_to_ifp(struct thread *td, const char *lxname)
+ifname_linux_to_ifp(const char *lxname)
{
struct ifname_linux_to_ifp_cb_s arg = {
- .ethno = 0,
.lxname = lxname,
- .ifp = NULL,
};
int len;
char *ep;
@@ -228,7 +240,7 @@
CURVNET_SET(TD_TO_VNET(td));
NET_EPOCH_ENTER(et);
- ifp = ifname_linux_to_ifp(td, lxname);
+ ifp = ifname_linux_to_ifp(lxname);
if (ifp != NULL && bsdname != NULL)
strlcpy(bsdname, if_name(ifp), IFNAMSIZ);
NET_EPOCH_EXIT(et);
diff --git a/sys/compat/linux/linux_netlink.c b/sys/compat/linux/linux_netlink.c
--- a/sys/compat/linux/linux_netlink.c
+++ b/sys/compat/linux/linux_netlink.c
@@ -248,10 +248,11 @@
nlmsg_translate_ifname_nla(struct nlattr *nla, struct nl_writer *nw)
{
char ifname[LINUX_IFNAMSIZ];
+ struct ifnet *ifp = nw->linux_cookie;
- if (ifname_bsd_to_linux_name((char *)(nla + 1), ifname,
- sizeof(ifname)) <= 0)
+ if (ifp == NULL)
return (false);
+ (void)ifname_bsd_to_linux_ifp(ifp, ifname, sizeof(ifname));
return (nlattr_add_string(nw, IFLA_IFNAME, ifname));
}
@@ -564,7 +565,7 @@
}
static struct nl_buf *
-nlmsgs_to_linux(struct nl_buf *orig, struct nlpcb *nlp)
+nlmsgs_to_linux(struct nl_buf *orig, struct nlpcb *nlp, void *cookie)
{
struct nl_writer nw;
u_int offset, msglen;
@@ -573,6 +574,7 @@
orig->datalen + SCRATCH_BUFFER_SIZE, nlp, false)))
return (NULL);
+ nw.linux_cookie = cookie;
/* Assume correct headers. Buffer IS mutable */
for (offset = 0;
offset + sizeof(struct nlmsghdr) <= orig->datalen;
diff --git a/sys/net/if_private.h b/sys/net/if_private.h
--- a/sys/net/if_private.h
+++ b/sys/net/if_private.h
@@ -65,6 +65,7 @@
void *if_linkmib; /* link-type-specific MIB data */
size_t if_linkmiblen; /* length of above data */
u_int if_refcount; /* reference count */
+ u_int if_linux_ethno; /* linux name id for IFT_ETHER */
/* These fields are shared with struct if_data. */
uint8_t if_type; /* ethernet, tokenring, etc */
diff --git a/sys/netlink/netlink_io.c b/sys/netlink/netlink_io.c
--- a/sys/netlink/netlink_io.c
+++ b/sys/netlink/netlink_io.c
@@ -217,7 +217,8 @@
}
if (nlp->nl_linux && linux_netlink_p != NULL) {
- nb = linux_netlink_p->msgs_to_linux(nw->buf, nlp);
+ nb = linux_netlink_p->msgs_to_linux(nw->buf, nlp,
+ nw->linux_cookie);
nl_buf_free(nw->buf);
nw->buf = NULL;
if (nb == NULL)
diff --git a/sys/netlink/netlink_linux.h b/sys/netlink/netlink_linux.h
--- a/sys/netlink/netlink_linux.h
+++ b/sys/netlink/netlink_linux.h
@@ -37,7 +37,8 @@
struct nl_pstate;
struct nl_writer;
-typedef struct nl_buf * msgs_to_linux_cb_t(struct nl_buf *, struct nlpcb *);
+typedef struct nl_buf * msgs_to_linux_cb_t(struct nl_buf *, struct nlpcb *,
+ void *);
typedef int msg_from_linux_cb_t(int netlink_family, struct nlmsghdr **hdr,
struct nl_pstate *npt);
diff --git a/sys/netlink/netlink_message_writer.h b/sys/netlink/netlink_message_writer.h
--- a/sys/netlink/netlink_message_writer.h
+++ b/sys/netlink/netlink_message_writer.h
@@ -53,6 +53,7 @@
int priv;
} group;
};
+ void *linux_cookie; /* Extra data for Linux translation */
u_int num_messages; /* Number of messages in the buffer */
int malloc_flag; /* M_WAITOK or M_NOWAIT */
bool ignore_limit; /* If true, ignores RCVBUF limit */
diff --git a/sys/netlink/route/iface.c b/sys/netlink/route/iface.c
--- a/sys/netlink/route/iface.c
+++ b/sys/netlink/route/iface.c
@@ -363,6 +363,8 @@
ifc_dump_ifp_nl(ifp, nw);
+ nw->linux_cookie = ifp;
+
if (nlmsg_end(nw))
return (true);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Jan 15, 11:24 AM (3 h, 48 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27647748
Default Alt Text
D54077.id167558.diff (11 KB)
Attached To
Mode
D54077: linux: store Linux Ethernet interface number in struct ifnet
Attached
Detach File
Event Timeline
Log In to Comment