Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F106950216
D38714.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D38714.diff
View Options
diff --git a/sys/compat/linprocfs/linprocfs.c b/sys/compat/linprocfs/linprocfs.c
--- a/sys/compat/linprocfs/linprocfs.c
+++ b/sys/compat/linprocfs/linprocfs.c
@@ -111,6 +111,7 @@
#endif /* __i386__ || __amd64__ */
#include <compat/linux/linux.h>
+#include <compat/linux/linux_common.h>
#include <compat/linux/linux_emul.h>
#include <compat/linux/linux_mib.h>
#include <compat/linux/linux_misc.h>
@@ -1474,36 +1475,13 @@
return (error);
}
-static int
-linux_ifname(struct ifnet *ifp, char *buffer, size_t buflen)
-{
- struct ifnet *ifscan;
- int ethno;
-
- IFNET_RLOCK_ASSERT();
-
- /* Short-circuit non ethernet interfaces */
- if (linux_use_real_ifname(ifp))
- return (strlcpy(buffer, ifp->if_xname, buflen));
-
- /* Determine the (relative) unit number for ethernet interfaces */
- ethno = 0;
- CK_STAILQ_FOREACH(ifscan, &V_ifnet, if_link) {
- if (ifscan == ifp)
- return (snprintf(buffer, buflen, "eth%d", ethno));
- if (!linux_use_real_ifname(ifscan))
- ethno++;
- }
-
- return (0);
-}
-
/*
* Filler function for proc/net/dev
*/
static int
linprocfs_donetdev(PFS_FILL_ARGS)
{
+ struct epoch_tracker et;
char ifname[16]; /* XXX LINUX_IFNAMSIZ */
struct ifnet *ifp;
@@ -1515,9 +1493,9 @@
"bytes packets errs drop fifo colls carrier compressed");
CURVNET_SET(TD_TO_VNET(curthread));
- IFNET_RLOCK();
+ NET_EPOCH_ENTER(et);
CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) {
- linux_ifname(ifp, ifname, sizeof ifname);
+ ifname_bsd_to_linux_ifp(ifp, ifname, sizeof(ifname));
sbuf_printf(sb, "%6.6s: ", ifname);
sbuf_printf(sb, "%7ju %7ju %4ju %4ju %4lu %5lu %10lu %9ju ",
(uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_IBYTES),
@@ -1546,7 +1524,7 @@
* tx_heartbeat_errors*/
0UL); /* tx_compressed */
}
- IFNET_RUNLOCK();
+ NET_EPOCH_EXIT(et);
CURVNET_RESTORE();
return (0);
@@ -1576,7 +1554,8 @@
/* select only first route in case of multipath */
nh = nhop_select_func(rnd.rnd_nhop, 0);
- linux_ifname(nh->nh_ifp, ifname, sizeof(ifname));
+ if (ifname_bsd_to_linux_ifp(nh->nh_ifp, ifname, sizeof(ifname)) <= 0)
+ return (ENODEV);
gw = (nh->nh_flags & NHF_GATEWAY)
? nh->gw4_sa.sin_addr.s_addr : 0;
@@ -1605,6 +1584,7 @@
static int
linprocfs_donetroute(PFS_FILL_ARGS)
{
+ struct epoch_tracker et;
struct walkarg w = {
.sb = sb
};
@@ -1615,9 +1595,9 @@
"\tWindow\tIRTT");
CURVNET_SET(TD_TO_VNET(curthread));
- IFNET_RLOCK();
+ NET_EPOCH_ENTER(et);
rib_walk(fibnum, AF_INET, false, linux_route_print, &w);
- IFNET_RUNLOCK();
+ NET_EPOCH_EXIT(et);
CURVNET_RESTORE();
return (0);
diff --git a/sys/compat/linux/linux.c b/sys/compat/linux/linux.c
--- a/sys/compat/linux/linux.c
+++ b/sys/compat/linux/linux.c
@@ -241,6 +241,84 @@
}
}
+/*
+ * 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)
+{
+ struct epoch_tracker et;
+ struct ifnet *ifp;
+ int ret;
+
+ ret = 0;
+ CURVNET_SET(TD_TO_VNET(curthread));
+ NET_EPOCH_ENTER(et);
+ ifp = ifunit(bsdname);
+ if (ifp != NULL)
+ ret = ifname_bsd_to_linux_ifp(ifp, lxname, len);
+ NET_EPOCH_EXIT(et);
+ CURVNET_RESTORE();
+ return (ret);
+}
+
+/*
+ * Translate a FreeBSD interface name to a Linux interface name
+ * by interface index, and return the number of bytes copied to lxname.
+ */
+int
+ifname_bsd_to_linux_idx(u_int idx, char *lxname, size_t len)
+{
+ struct epoch_tracker et;
+ struct ifnet *ifp;
+ int ret;
+
+ ret = 0;
+ CURVNET_SET(TD_TO_VNET(curthread));
+ NET_EPOCH_ENTER(et);
+ ifp = ifnet_byindex(idx);
+ if (ifp != NULL)
+ ret = ifname_bsd_to_linux_ifp(ifp, lxname, len);
+ NET_EPOCH_EXIT(et);
+ CURVNET_RESTORE();
+ return (ret);
+}
+
+/*
+ * Translate a FreeBSD interface name to a Linux interface name,
+ * and return the number of bytes copied to lxname.
+ */
+int
+ifname_bsd_to_linux_ifp(struct ifnet *ifp, char *lxname, size_t len)
+{
+ struct ifnet *ifscan;
+ int unit;
+
+ 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(ifp->if_xname, "lo0", IFNAMSIZ) == 0)
+ return (strlcpy(lxname, "lo", len));
+
+ /* Short-circuit non ethernet interfaces. */
+ if (!IFP_IS_ETH(ifp) || linux_use_real_ifname(ifp))
+ return (strlcpy(lxname, ifp->if_xname, len));
+
+ /* Determine the (relative) unit number for ethernet interfaces. */
+ unit = 0;
+ CK_STAILQ_FOREACH(ifscan, &V_ifnet, if_link) {
+ if (ifscan == ifp)
+ return (snprintf(lxname, len, "eth%d", unit));
+ if (IFP_IS_ETH(ifscan))
+ unit++;
+ }
+ return (0);
+}
+
/*
* Translate a Linux interface name to a FreeBSD interface name,
* and return the associated ifnet structure
@@ -261,8 +339,11 @@
break;
if (len == 0 || len == LINUX_IFNAMSIZ)
return (NULL);
- /* Linux loopback interface name is lo (not lo0) */
- is_lo = (len == 2 && strncmp(lxname, "lo", len) == 0);
+ /*
+ * Linux loopback interface name is lo (not lo0),
+ * we translate lo to lo0, loX to loX.
+ */
+ is_lo = (len == 2 && strncmp(lxname, "lo", LINUX_IFNAMSIZ) == 0);
unit = (int)strtoul(lxname + len, &ep, 10);
if ((ep == NULL || ep == lxname + len || ep >= lxname + LINUX_IFNAMSIZ) &&
is_lo == 0)
@@ -732,5 +813,5 @@
linux_use_real_ifname(const struct ifnet *ifp)
{
- return (use_real_ifnames || !IFP_IS_ETH(ifp));
+ return (use_real_ifnames);
}
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,6 +30,10 @@
#ifndef _LINUX_COMMON_H_
#define _LINUX_COMMON_H_
+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_bsd(struct thread *td,
const char *lxname, char *bsdname);
void linux_ifflags(struct ifnet *ifp, short *flags);
diff --git a/sys/compat/linux/linux_ioctl.c b/sys/compat/linux/linux_ioctl.c
--- a/sys/compat/linux/linux_ioctl.c
+++ b/sys/compat/linux/linux_ioctl.c
@@ -2092,39 +2092,17 @@
linux_ioctl_ifname(struct thread *td, struct l_ifreq *uifr)
{
struct l_ifreq ifr;
- struct ifnet *ifp;
- int error, ethno, index;
+ int error, ret;
error = copyin(uifr, &ifr, sizeof(ifr));
if (error != 0)
return (error);
-
- CURVNET_SET(TD_TO_VNET(curthread));
- IFNET_RLOCK();
- index = 1; /* ifr.ifr_ifindex starts from 1 */
- ethno = 0;
- error = ENODEV;
- CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) {
- if (ifr.ifr_ifindex == index) {
- if (!linux_use_real_ifname(ifp))
- snprintf(ifr.ifr_name, LINUX_IFNAMSIZ,
- "eth%d", ethno);
- else
- strlcpy(ifr.ifr_name, ifp->if_xname,
- LINUX_IFNAMSIZ);
- error = 0;
- break;
- }
- if (!linux_use_real_ifname(ifp))
- ethno++;
- index++;
- }
- IFNET_RUNLOCK();
- if (error == 0)
- error = copyout(&ifr, uifr, sizeof(ifr));
- CURVNET_RESTORE();
-
- return (error);
+ ret = ifname_bsd_to_linux_idx(ifr.ifr_ifindex, ifr.ifr_name,
+ LINUX_IFNAMSIZ);
+ if (ret > 0)
+ return (copyout(&ifr, uifr, sizeof(ifr)));
+ else
+ return (ENODEV);
}
/*
@@ -2134,6 +2112,7 @@
static int
linux_ifconf(struct thread *td, struct ifconf *uifc)
{
+ struct epoch_tracker et;
#ifdef COMPAT_LINUX32
struct l_ifconf ifc;
#else
@@ -2143,7 +2122,7 @@
struct ifnet *ifp;
struct ifaddr *ifa;
struct sbuf *sb;
- int error, ethno, full = 0, valid_len, max_len;
+ int error, full = 0, valid_len, max_len;
error = copyin(uifc, &ifc, sizeof(ifc));
if (error != 0)
@@ -2155,7 +2134,7 @@
/* handle the 'request buffer size' case */
if ((l_uintptr_t)ifc.ifc_buf == PTROUT(NULL)) {
ifc.ifc_len = 0;
- IFNET_RLOCK();
+ NET_EPOCH_ENTER(et);
CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) {
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
struct sockaddr *sa = ifa->ifa_addr;
@@ -2163,7 +2142,7 @@
ifc.ifc_len += sizeof(ifr);
}
}
- IFNET_RUNLOCK();
+ NET_EPOCH_EXIT(et);
error = copyout(&ifc, uifc, sizeof(ifc));
CURVNET_RESTORE();
return (error);
@@ -2175,8 +2154,6 @@
}
again:
- /* Keep track of eth interfaces */
- ethno = 0;
if (ifc.ifc_len <= max_len) {
max_len = ifc.ifc_len;
full = 1;
@@ -2186,16 +2163,13 @@
valid_len = 0;
/* Return all AF_INET addresses of all interfaces */
- IFNET_RLOCK();
+ NET_EPOCH_ENTER(et);
CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) {
int addrs = 0;
bzero(&ifr, sizeof(ifr));
- if (IFP_IS_ETH(ifp))
- snprintf(ifr.ifr_name, LINUX_IFNAMSIZ, "eth%d",
- ethno++);
- else
- strlcpy(ifr.ifr_name, ifp->if_xname, LINUX_IFNAMSIZ);
+ ifname_bsd_to_linux_ifp(ifp, ifr.ifr_name,
+ sizeof(ifr.ifr_name));
/* Walk the address list */
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
@@ -2222,7 +2196,7 @@
valid_len = sbuf_len(sb);
}
}
- IFNET_RUNLOCK();
+ NET_EPOCH_EXIT(et);
if (valid_len != max_len && !full) {
sbuf_delete(sb);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Jan 8, 11:08 PM (4 h, 3 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15727207
Default Alt Text
D38714.diff (8 KB)
Attached To
Mode
D38714: linux(4): Consolidate a FreeBSD interface names translation code
Attached
Detach File
Event Timeline
Log In to Comment