FreeBSD Bugzilla – Attachment 188080 Details for
Bug 223722
update linsysfs to include /sys/class/net data
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
Changes to add /sys/class/net nodes
linsysfs.c (text/plain), 15.89 KB, created by
neirac
on 2017-11-17 20:04:54 UTC
(
hide
)
Description:
Changes to add /sys/class/net nodes
Filename:
MIME Type:
Creator:
neirac
Created:
2017-11-17 20:04:54 UTC
Size:
15.89 KB
patch
obsolete
>/*- >* Copyright (c) 2006 IronPort Systems >* Copyright (c) 2017 Carlos Neira cneirabustos@gmail.com >* All rights reserved. >* >* Redistribution and use in source and binary forms, with or without >* modification, are permitted provided that the following conditions >* are met: >* 1. Redistributions of source code must retain the above copyright >* notice, this list of conditions and the following disclaimer. >* 2. Redistributions in binary form must reproduce the above copyright >* notice, this list of conditions and the following disclaimer in the >* documentation and/or other materials provided with the distribution. >* >* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND >* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE >* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE >* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL >* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS >* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) >* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT >* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY >* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF >* SUCH DAMAGE. >*/ > >#include <sys/cdefs.h> >__FBSDID("$FreeBSD$"); > >#include <sys/param.h> >#include <sys/systm.h> >#include <sys/queue.h> >#include <sys/blist.h> >#include <sys/conf.h> >#include <sys/exec.h> >#include <sys/filedesc.h> >#include <sys/kernel.h> >#include <sys/linker.h> >#include <sys/malloc.h> >#include <sys/mount.h> >#include <sys/mutex.h> >#include <sys/proc.h> >#include <sys/resourcevar.h> >#include <sys/sbuf.h> >#include <sys/smp.h> >#include <sys/socket.h> >#include <sys/vnode.h> >#include <sys/bus.h> >#include <sys/pciio.h> > >#include <dev/pci/pcivar.h> >#include <dev/pci/pcireg.h> > >#include <sys/ctype.h> >#include <net/if.h> >#include <net/if_types.h> >#include <net/if_var.h> >#include <net/if_dl.h> >#include <net/vnet.h> > >#include <vm/vm.h> >#include <vm/pmap.h> >#include <vm/vm_map.h> >#include <vm/vm_param.h> >#include <vm/vm_object.h> >#include <vm/swap_pager.h> > >#include <machine/bus.h> > >#include <compat/linux/linux_ioctl.h> >#include <compat/linux/linux_mib.h> >#include <compat/linux/linux_util.h> >#include <fs/pseudofs/pseudofs.h> >#include <sys/jail.h> > >#define LINUX_IFNAMSIZ 16 > > >struct scsi_host_queue { > TAILQ_ENTRY(scsi_host_queue) scsi_host_next; > char *path; > char *name; >}; > >TAILQ_HEAD(,scsi_host_queue) scsi_host_q; > >static int host_number = 0; > > >static int >atoi(const char *str) >{ > return (int)strtol(str, (char **)NULL, 10); >} > >/* >* Filler function for proc_name >*/ >static int >linsysfs_scsiname(PFS_FILL_ARGS) >{ > struct scsi_host_queue *scsi_host; > int index; > > if (strncmp(pn->pn_parent->pn_name, "host", 4) == 0) { > index = atoi(&pn->pn_parent->pn_name[4]); > } else { > sbuf_printf(sb, "unknown\n"); > return (0); > } > TAILQ_FOREACH(scsi_host, &scsi_host_q, scsi_host_next) { > if (index-- == 0) { > sbuf_printf(sb, "%s\n", scsi_host->name); > return (0); > } > } > sbuf_printf(sb, "unknown\n"); > return (0); >} > >/* >* Filler function for device sym-link >*/ >static int >linsysfs_link_scsi_host(PFS_FILL_ARGS) >{ > struct scsi_host_queue *scsi_host; > int index; > > if (strncmp(pn->pn_parent->pn_name, "host", 4) == 0) { > index = atoi(&pn->pn_parent->pn_name[4]); > } else { > sbuf_printf(sb, "unknown\n"); > return (0); > } > TAILQ_FOREACH(scsi_host, &scsi_host_q, scsi_host_next) { > if (index-- == 0) { > sbuf_printf(sb, "../../../devices%s", scsi_host->path); > return(0); > } > } > sbuf_printf(sb, "unknown\n"); > return (0); >} > >#define PCI_DEV "pci" >static int >linsysfs_run_bus(device_t dev, struct pfs_node *dir, struct pfs_node *scsi, char *path, > char *prefix) >{ > struct scsi_host_queue *scsi_host; > struct pfs_node *sub_dir; > int i, nchildren; > device_t *children, parent; > devclass_t devclass; > const char *name = NULL; > struct pci_devinfo *dinfo; > char *device, *host, *new_path = path; > > parent = device_get_parent(dev); > if (parent) { > devclass = device_get_devclass(parent); > if (devclass != NULL) > name = devclass_get_name(devclass); > if (name && strcmp(name, PCI_DEV) == 0) { > dinfo = device_get_ivars(dev); > if (dinfo) { > device = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); > new_path = malloc(MAXPATHLEN, M_TEMP, > M_WAITOK); > new_path[0] = '\000'; > strcpy(new_path, path); > host = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); > device[0] = '\000'; > sprintf(device, "%s:%02x:%02x.%x", > prefix, > dinfo->cfg.bus, > dinfo->cfg.slot, > dinfo->cfg.func); > strcat(new_path, "/"); > strcat(new_path, device); > dir = pfs_create_dir(dir, device, > NULL, NULL, NULL, 0); > > if (dinfo->cfg.baseclass == PCIC_STORAGE) { > /* DJA only make this if needed */ > sprintf(host, "host%d", host_number++); > strcat(new_path, "/"); > strcat(new_path, host); > pfs_create_dir(dir, host, > NULL, NULL, NULL, 0); > scsi_host = malloc(sizeof( > struct scsi_host_queue), > M_DEVBUF, M_NOWAIT); > scsi_host->path = malloc( > strlen(new_path) + 1, > M_DEVBUF, M_NOWAIT); > scsi_host->path[0] = '\000'; > bcopy(new_path, scsi_host->path, > strlen(new_path) + 1); > scsi_host->name = "unknown"; > > sub_dir = pfs_create_dir(scsi, host, > NULL, NULL, NULL, 0); > pfs_create_link(sub_dir, "device", > &linsysfs_link_scsi_host, > NULL, NULL, NULL, 0); > pfs_create_file(sub_dir, "proc_name", > &linsysfs_scsiname, > NULL, NULL, NULL, PFS_RD); > scsi_host->name > = linux_driver_get_name_dev(dev); > TAILQ_INSERT_TAIL(&scsi_host_q, > scsi_host, scsi_host_next); > } > free(device, M_TEMP); > free(host, M_TEMP); > } > } > } > > device_get_children(dev, &children, &nchildren); > for (i = 0; i < nchildren; i++) { > if (children[i]) > linsysfs_run_bus(children[i], dir, scsi, new_path, prefix); > } > if (new_path != path) > free(new_path, M_TEMP); > > return (1); >} > >/* >* Filler function for sys/devices/system/cpu/online >*/ >static int >linsysfs_cpuonline(PFS_FILL_ARGS) >{ > > sbuf_printf(sb, "%d-%d\n", CPU_FIRST(), mp_maxid); > return (0); >} > >/* >* Filler function for sys/devices/system/cpu/cpuX/online >*/ >static int >linsysfs_cpuxonline(PFS_FILL_ARGS) >{ > > sbuf_printf(sb, "1\n"); > return (0); >} > >static void >linsysfs_listcpus(struct pfs_node *dir) >{ > struct pfs_node *cpu; > char *name; > int i, count, len; > > len = 1; > count = mp_maxcpus; > while (count > 10) { > count /= 10; > len++; > } > len += sizeof("cpu"); > name = malloc(len, M_TEMP, M_WAITOK); > > for (i = 0; i < mp_ncpus; ++i) { > /* /sys/devices/system/cpu/cpuX */ > sprintf(name, "cpu%d", i); > cpu = pfs_create_dir(dir, name, NULL, NULL, NULL, 0); > > pfs_create_file(cpu, "online", &linsysfs_cpuxonline, > NULL, NULL, NULL, PFS_RD); > } > free(name, M_TEMP); >} > >/* >* Filler function for sys/class/net/<iface> >* Used as reference >* https://grok.elemental.org/source/xref/illumos-joyent/usr/src/uts/common/brand/lx/sysfs/lx_sysvnops.c >* and Linux kernel documentation for /sys/class/net >* Only 2 interfaces are created eth0 and lo and they expose the following files >* to make applications work: >* address, addr_len, flags, ifindex, mty, tx_queue_len and type >*/ >#define ETHERADDRL 6 >#define IFP_IS_ETH(ifp) (ifp->if_type == IFT_ETHER) >static struct ifnet * >ifname_linux_to_bsd(struct thread *td, const char *lxname, char *bsdname) >{ > struct ifnet *ifp; > int len, unit; > char *ep; > int is_eth, index; > > for (len = 0; len < LINUX_IFNAMSIZ; ++len) > if (!isalpha(lxname[len])) > break; > if (len == 0 || len == LINUX_IFNAMSIZ) > return (NULL); > unit = (int)strtoul(lxname + len, &ep, 10); > if (ep == NULL || ep == lxname + len || ep >= lxname + LINUX_IFNAMSIZ) > return (NULL); > index = 0; > is_eth = (len == 3 && !strncmp(lxname, "eth", len)) ? 1 : 0; > CURVNET_SET(TD_TO_VNET(td)); > IFNET_RLOCK(); > TAILQ_FOREACH(ifp, &V_ifnet, if_link) { > /* > * Allow Linux programs to use FreeBSD names. Don't presume > * we never have an interface named "eth", so don't make > * the test optional based on is_eth. > */ > if (strncmp(ifp->if_xname, lxname, LINUX_IFNAMSIZ) == 0) > break; > if (is_eth && IFP_IS_ETH(ifp) && unit == index++) > break; > } > IFNET_RUNLOCK(); > CURVNET_RESTORE(); > if (ifp != NULL) > strlcpy(bsdname, ifp->if_xname, IFNAMSIZ); > return (ifp); >} > >static int >linsysfs_ifnet_addr (PFS_FILL_ARGS) { > struct ifnet* ifp; > char bsdname[IFNAMSIZ+1]; > uint8_t* address; > if (!memcmp((const char*)pn->pn_parent->pn_name,"lo",2)) { > sbuf_printf (sb, "00:00:00:00:00:00\n"); > return (0); > } else { > ifp = ifname_linux_to_bsd(curthread,(const char*)pn->pn_parent->pn_name,bsdname); > if (!ifp) { > sbuf_printf (sb, "00:00:00:00:00:00\n"); > return (0); > } > address = IF_LLADDR(ifp); > sbuf_printf (sb,"%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n", > address[0], address[1], address[2], > address[3], address[4], address[5]); > return (0); > } >} >//https://grok.elemental.org/source/xref/illumos-joyent/usr/src/uts/common/brand/lx/sysfs/lx_sysvnops.c#LXSYS_ENDP_NET_ADDRLEN >static int >linsysfs_ifnet_addrlen (PFS_FILL_ARGS) { > sbuf_printf(sb,"6\n"); > return (0); >} >//;https://grok.elemental.org/source/xref/illumos-joyent/usr/src/uts/common/brand/lx/os/lx_misc.c#859 >static int >linsysfs_ifnet_flags (PFS_FILL_ARGS) { > int buf; > struct ifnet* ifp; > char bsdname[IFNAMSIZ+1]; > if (!memcmp((const char*)pn->pn_parent->pn_name,"eth",3)) { > > ifp = ifname_linux_to_bsd(curthread,(const char*)pn->pn_parent->pn_name,bsdname); > buf = ifp->if_flags & (IFF_UP | IFF_BROADCAST | IFF_DEBUG | > IFF_LOOPBACK | IFF_POINTOPOINT | > IFF_DRV_RUNNING | IFF_NOARP | IFF_PROMISC | IFF_ALLMULTI); > buf |= 0x1000; > sbuf_printf(sb,"0x%x\n",buf); > } else { > sbuf_printf(sb,"0x9\n"); > } > return (0); >} >static int >linsysfs_ifnet_ifindex (PFS_FILL_ARGS) { > struct ifnet* ifp; > char bsdname[IFNAMSIZ+1]; > if (!memcmp((const char*)pn->pn_parent->pn_name,"eth",3)) { > ifp = ifname_linux_to_bsd(curthread,(const char*)pn->pn_parent->pn_name,bsdname); > sbuf_printf(sb,"%u\n",ifp->if_index); > } else { > sbuf_printf(sb,"1\n"); > } > return (0); >} >static int >linsysfs_ifnet_mtu (PFS_FILL_ARGS) { > struct ifnet* ifp; > char bsdname[IFNAMSIZ+1]; > if (!memcmp((const char*)pn->pn_parent->pn_name,"lo",2)) { > sbuf_printf(sb,"65536\n"); > } else { > ifp = ifname_linux_to_bsd(curthread,(const char*)pn->pn_parent->pn_name,bsdname); > sbuf_printf(sb,"%u\n",ifp->if_mtu); > } > return (0); >} > >static int >linsysfs_ifnet_tx_queue_len (PFS_FILL_ARGS) { > sbuf_printf(sb,"1000\n"); > return (0); >} >static int >linsysfs_ifnet_type (PFS_FILL_ARGS) { > if (!memcmp((const char*)pn->pn_parent->pn_name,"lo",2)) > sbuf_printf(sb,"772\n"); > else > sbuf_printf(sb,"2\n"); > return (0); >} > > > >static void >linsysfs_listnics (struct pfs_node *dir) >{ > > struct pfs_node *nic; > struct pfs_node *lo; > > nic = pfs_create_dir (dir, "eth0", NULL, NULL, NULL, 0); > > pfs_create_file (nic, "address", &linsysfs_ifnet_addr, > NULL, NULL, NULL, PFS_RD); > > pfs_create_file (nic, "addr_len", &linsysfs_ifnet_addrlen, > NULL, NULL, NULL, PFS_RD); > > pfs_create_file (nic, "flags", &linsysfs_ifnet_flags, > NULL, NULL, NULL, PFS_RD); > > pfs_create_file (nic, "ifindex", &linsysfs_ifnet_ifindex, > NULL, NULL, NULL, PFS_RD); > > pfs_create_file (nic, "mtu", &linsysfs_ifnet_mtu, > NULL, NULL, NULL, PFS_RD); > > pfs_create_file (nic, "tx_queue_len", &linsysfs_ifnet_tx_queue_len, > NULL, NULL, NULL, PFS_RD); > > pfs_create_file (nic, "type", &linsysfs_ifnet_type, > NULL, NULL, NULL, PFS_RD); > > lo = pfs_create_dir (dir, "lo", NULL, NULL, NULL, 0); > > pfs_create_file (lo, "address", &linsysfs_ifnet_addr, > NULL, NULL, NULL, PFS_RD); > > pfs_create_file (lo, "addr_len", &linsysfs_ifnet_addrlen, > NULL, NULL, NULL, PFS_RD); > > pfs_create_file (lo, "flags", &linsysfs_ifnet_flags, > NULL, NULL, NULL, PFS_RD); > > pfs_create_file (lo, "ifindex", &linsysfs_ifnet_ifindex, > NULL, NULL, NULL, PFS_RD); > > pfs_create_file (lo, "mtu", &linsysfs_ifnet_mtu, > NULL, NULL, NULL, PFS_RD); > > pfs_create_file (lo, "tx_queue_len", &linsysfs_ifnet_tx_queue_len, > NULL, NULL, NULL, PFS_RD); > > pfs_create_file (lo, "type", &linsysfs_ifnet_type, > NULL, NULL, NULL, PFS_RD); > >} > >/* >* Constructor >*/ >static int >linsysfs_init(PFS_INIT_ARGS) >{ > struct pfs_node *root; > struct pfs_node *dir, *sys, *cpu; > struct pfs_node *pci; > struct pfs_node *scsi; > struct pfs_node *net; > devclass_t devclass; > device_t dev; > > TAILQ_INIT(&scsi_host_q); > > root = pi->pi_root; > > /* /sys/class/... */ > scsi = pfs_create_dir(root, "class", NULL, NULL, NULL, 0); > > /* /sys/class/net/.. */ > net = pfs_create_dir(scsi, "net", NULL, NULL, NULL, 0); > > scsi = pfs_create_dir(scsi, "scsi_host", NULL, NULL, NULL, 0); > > /* /sys/devices */ > dir = pfs_create_dir(root, "devices", NULL, NULL, NULL, 0); > > /* /sys/devices/pci0000:00 */ > pci = pfs_create_dir(dir, "pci0000:00", NULL, NULL, NULL, 0); > > devclass = devclass_find("root"); > if (devclass == NULL) { > return (0); > } > > dev = devclass_get_device(devclass, 0); > linsysfs_run_bus(dev, pci, scsi, "/pci0000:00", "0000"); > > /* /sys/devices/system */ > sys = pfs_create_dir(dir, "system", NULL, NULL, NULL, 0); > > /* /sys/devices/system/cpu */ > cpu = pfs_create_dir(sys, "cpu", NULL, NULL, NULL, 0); > > pfs_create_file(cpu, "online", &linsysfs_cpuonline, > NULL, NULL, NULL, PFS_RD); > > linsysfs_listcpus(cpu); > linsysfs_listnics(net); > > return (0); >} > >/* >* Destructor >*/ >static int >linsysfs_uninit(PFS_INIT_ARGS) >{ > struct scsi_host_queue *scsi_host, *scsi_host_tmp; > > TAILQ_FOREACH_SAFE(scsi_host, &scsi_host_q, scsi_host_next, > scsi_host_tmp) { > TAILQ_REMOVE(&scsi_host_q, scsi_host, scsi_host_next); > free(scsi_host->path, M_TEMP); > free(scsi_host, M_TEMP); > } > > return (0); >} > > > > > >PSEUDOFS(linsysfs, 1, PR_ALLOW_MOUNT_LINSYSFS); >#if defined(__amd64__) >MODULE_DEPEND(linsysfs, linux_common, 1, 1, 1); >#else >MODULE_DEPEND(linsysfs, linux, 1, 1, 1); >#endif
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 223722
: 188080 |
188232