Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144614519
D54077.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
D54077.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
@@ -28,10 +28,9 @@
#ifndef _LINUX_COMMON_H_
#define _LINUX_COMMON_H_
-int ifname_bsd_to_linux_ifp(struct ifnet *, char *, size_t);
+int ifname_bsd_to_linux_ifp(const 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,67 @@
&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
/*
* Translate a FreeBSD interface name to a Linux interface name
@@ -99,50 +137,23 @@
* 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)
+ifname_bsd_to_linux_ifp(const 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.
*/
- if (IFP_IS_LOOP(ifp) && strncmp(if_name(ifp), "lo0", IFNAMSIZ) == 0)
+ if (ifp->if_type == IFT_LOOP &&
+ strncmp(ifp->if_xname, "lo0", IFNAMSIZ) == 0)
return (strlcpy(lxname, "lo", len));
/* Short-circuit non ethernet interfaces. */
- if (!IFP_IS_ETH(ifp) || use_real_ifnames)
- return (strlcpy(lxname, if_name(ifp), len));
+ if (ifp->if_type != IFT_ETHER || use_real_ifnames)
+ return (strlcpy(lxname, ifp->if_xname, 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 +165,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 +184,11 @@
*/
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->if_type == IFT_ETHER &&
+ ifp->if_linux_ethno == cbs->unit)
goto out;
- if (cbs->is_lo && IFP_IS_LOOP(ifp))
+ if (cbs->is_lo && ifp->if_type == IFT_LOOP)
goto out;
- if (IFP_IS_ETH(ifp))
- cbs->ethno++;
return (0);
out:
@@ -188,12 +197,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 +235,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);
@@ -297,12 +304,12 @@
NET_EPOCH_ASSERT();
- if (IFP_IS_LOOP(ifp)) {
+ if (ifp->if_type == IFT_LOOP) {
bzero(lsa, sizeof(*lsa));
lsa->sa_family = LINUX_ARPHRD_LOOPBACK;
return (0);
}
- if (!IFP_IS_ETH(ifp))
+ if (ifp->if_type != IFT_ETHER)
return (ENOENT);
if (if_foreach_addr_type(ifp, AF_LINK, linux_ifhwaddr_cb, lsa) > 0)
return (0);
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
@@ -249,9 +249,9 @@
{
char ifname[LINUX_IFNAMSIZ];
- if (ifname_bsd_to_linux_name((char *)(nla + 1), ifname,
- sizeof(ifname)) <= 0)
+ if (nw->ifp == NULL)
return (false);
+ (void)ifname_bsd_to_linux_ifp(nw->ifp, ifname, sizeof(ifname));
return (nlattr_add_string(nw, IFLA_IFNAME, ifname));
}
@@ -564,7 +564,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, const struct ifnet *ifp)
{
struct nl_writer nw;
u_int offset, msglen;
@@ -573,6 +573,7 @@
orig->datalen + SCRATCH_BUFFER_SIZE, nlp, false)))
return (NULL);
+ nw.ifp = ifp;
/* 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,7 @@
}
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->ifp);
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 *,
+ const struct ifnet *);
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
@@ -39,6 +39,7 @@
struct nl_buf;
struct nl_writer;
+struct ifnet;
typedef bool nl_writer_cb(struct nl_writer *nw);
struct nl_writer {
@@ -53,6 +54,7 @@
int priv;
} group;
};
+ const struct ifnet *ifp; /* Used by Linux translation only */
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->ifp = ifp;
+
if (nlmsg_end(nw))
return (true);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Feb 11, 7:01 AM (9 h, 59 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28640973
Default Alt Text
D54077.diff (12 KB)
Attached To
Mode
D54077: linux: store Linux Ethernet interface number in struct ifnet
Attached
Detach File
Event Timeline
Log In to Comment