Page MenuHomeFreeBSD

D54077.id167558.diff
No OneTemporary

D54077.id167558.diff

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

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)

Event Timeline