Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Leap:42.1:Staging:C
fcoe-utils
0009-fcoe-utils-Add-sysfs_hba-to-to-fcoemon_uti...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0009-fcoe-utils-Add-sysfs_hba-to-to-fcoemon_utils.patch of Package fcoe-utils
From 883bf545d51aa3ce0cb712b44db19e3fcc0714f9 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn <jthumshirn@suse.de> Date: Thu, 30 Jul 2015 15:06:15 +0200 Subject: [PATCH] fcoe-utils: Add sysfs_hba to to fcoemon_utils Add sysfs_hba to to fcoemon_utils. This is the 1st part of obsoleting libHBAAPI2 and libhbalinux2 for fcoe-utils. Signed-off-by: Johannes Thumshirn <jthumshirn@suse.de> --- Makefile.am | 7 +- configure.ac | 3 + fcoe-utils.spec.in | 2 +- include/sysfs_hba.h | 64 +++++++++ lib/sysfs_hba.c | 390 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 462 insertions(+), 4 deletions(-) create mode 100644 include/sysfs_hba.h create mode 100644 lib/sysfs_hba.c diff --git a/Makefile.am b/Makefile.am index c6599ef..59c197d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -9,7 +9,7 @@ AM_CFLAGS = -Wall -Wformat=2 -Werror -Wmissing-prototypes -Wstrict-prototypes ## rules for building fcoeadm fcoeadm_SOURCES = fcoeadm.c fcoeadm_display.c -fcoeadm_LDADD = lib/libutil.a libopenfcoe.a $(HBAAPI_LIBS) +fcoeadm_LDADD = lib/libutil.a libopenfcoe.a $(PCIACCESS_LIBS) $(HBAAPI_LIBS) fcoeadm_CFLAGS = $(AM_CFLAGS) $(HBAAPI_CFLAGS) ## rules for building fcoemon @@ -29,7 +29,8 @@ fipvlan_LDADD = lib/libutil.a AUTOMAKE_OPTIONS=subdir-objects noinst_LIBRARIES = lib/libutil.a libopenfcoe.a lib_libutil_a_SOURCES = lib/fcoe_utils.c lib/sa_log.c lib/sa_select.c \ - lib/sa_timer.c lib/sa_other.c lib/fip.c lib/rtnetlink.c lib/sa_sys.c + lib/sa_timer.c lib/sa_other.c lib/fip.c lib/rtnetlink.c lib/sa_sys.c \ + lib/sysfs_hba.c libopenfcoe_a_SOURCES = libopenfcoe.c ## header files that need to be distributed @@ -38,7 +39,7 @@ noinst_HEADERS = fcoeadm_display.h fcoe_clif.h fcoemon.h \ include/fc_types.h include/fip.h include/net_types.h include/rtnetlink.h \ include/libopenfcoe.h include/scsi_netlink_fc.h include/scsi_netlink.h \ include/strarr.h include/fc_ns.h include/fc_gs.h include/fc_els.h include/scsi_bsg_fc.h \ - include/linux/rtnetlink.h include/linux/types.h include/linux/dcbnl.h + include/sysfs_hba.h include/linux/rtnetlink.h include/linux/types.h include/linux/dcbnl.h ## install configuration file in $(prefix)/etc/fcoe fcoe_configdir = ${sysconfdir}/fcoe diff --git a/configure.ac b/configure.ac index ef0ffb1..5bafef3 100644 --- a/configure.ac +++ b/configure.ac @@ -17,6 +17,9 @@ AC_SUBST([LLDPAD_CFLAGS]) PKG_CHECK_MODULES([LIBHBALINUX], [libhbalinux >= 1.0.17]) AC_SUBST([LIBHBALINUX_CFLAGS]) +PKG_CHECK_MODULES([PCIACCESS], [pciaccess]) +AC_SUBST([PCIACCESS_LIBS]) + PKG_PROG_PKG_CONFIG AC_ARG_WITH([systemdsystemunitdir], AS_HELP_STRING([--with-systemdsystemunitdir=DIR], diff --git a/fcoe-utils.spec.in b/fcoe-utils.spec.in index d45b84b..dff3fbd 100644 --- a/fcoe-utils.spec.in +++ b/fcoe-utils.spec.in @@ -9,7 +9,7 @@ URL: http://www.open-fcoe.org Source0: http://www.open-fcoe.org/openfc/%{name}-%{version}.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) -BuildRequires: libHBAAPI-devel lldpad-devel +BuildRequires: libHBAAPI-devel lldpad-devel libpciaccess0 Requires: lldpad Requires(post): chkconfig Requires(preun): chkconfig initscripts diff --git a/include/sysfs_hba.h b/include/sysfs_hba.h new file mode 100644 index 0000000..1e62477 --- /dev/null +++ b/include/sysfs_hba.h @@ -0,0 +1,64 @@ +/* + * Copyright(c) 2015 SUSE GmbH. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + * Maintained at www.Open-FCoE.org + */ + +#ifndef _SYSFS_HBA_H +#define _SYSFS_HBA_H + +#include <stdint.h> + + +#define HBA_PORTSPEED_4GBIT 0x0008 /* 4 GBit/sec */ +#define HBA_PORTSPEED_8GBIT 0x0010 /* 8 GBit/sec */ +#define HBA_PORTSPEED_16GBIT 0x0020 /* 16 GBit/sec */ +#define HBA_PORTSPEED_32GBIT 0x0040 /* 32 GBit/sec */ +#define HBA_PORTSPEED_20GBIT 0x0080 /* 20 GBit/sec */ +#define HBA_PORTSPEED_40GBIT 0x0100 /* 40 GBit/sec */ +#define HBA_PORTSPEED_NOT_NEGOTIATED (1 << 15) /* Speed not established */ + +struct port_attributes { + char device_name[256]; + char symbolic_name[256]; + char node_name[256]; + char port_name[256]; + char fabric_name[256]; + char speed[256]; + char supported_speeds[256]; + char maxframe_size[256]; + char port_id[256]; + char port_state[256]; +}; + +struct hba_info { + char manufacturer[64]; + char serial_number[64]; + char model_description[256]; + char hardware_version[256]; + char driver_name[256]; + char driver_version[256]; + uint32_t nports; +}; + + +int get_number_of_adapters(void); +struct hba_info *get_hbainfo_by_pcidev(const char *pcidev); +struct port_attributes *get_port_attribs(const char *host); +char *get_pci_dev_from_netdev(const char *netdev); +char *get_host_from_netdev(const char *netdev); + +#endif /* _SYSFS_HBA_H */ diff --git a/lib/sysfs_hba.c b/lib/sysfs_hba.c new file mode 100644 index 0000000..e7f3e0b --- /dev/null +++ b/lib/sysfs_hba.c @@ -0,0 +1,390 @@ +/* + * Copyright(c) 2015 SUSE GmbH. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + * Maintained at www.Open-FCoE.org + */ + +#define _GNU_SOURCE + +#include <linux/pci_regs.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <dirent.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdint.h> +#include <inttypes.h> +#include <unistd.h> +#include <pciaccess.h> + +#include "sysfs_hba.h" +#include "fcoemon_utils.h" + +#define SYSFS_HOST_DIR "/sys/class/fc_host" +#define SYSFS_NET_DIR "/sys/class/net" + +static void get_device_serial_number(struct pci_device *dev, + struct hba_info *info) +{ + uint32_t pcie_cap_header; + uint32_t dword_high = 0; + uint32_t dword_low = 0; + uint16_t pcie_cap_id; + pciaddr_t offset; + uint16_t status; + uint8_t cap_ptr; + int rc; + + snprintf(info->serial_number, sizeof(info->serial_number), "Unknown"); + + rc = pci_device_cfg_read_u16(dev, &status, PCI_STATUS); + if (rc) { + fprintf(stderr, "Failed reading PCI status register\n"); + return; + } + + if (!(status & PCI_STATUS_CAP_LIST)) { + fprintf(stderr, "PCI capabilities are not supported\n"); + return; + } + + rc = pci_device_cfg_read_u8(dev, &cap_ptr, PCI_CAPABILITY_LIST); + if (rc) { + fprintf(stderr, "Failed reading PCI Capability List Register\n"); + return; + } + + offset = cap_ptr; + + while (offset) { + uint8_t next_cap; + uint8_t cap_id; + + rc = pci_device_cfg_read_u8(dev, &cap_id, offset + PCI_CAP_LIST_ID); + if (rc) { + fprintf(stderr, "Failed reading capability ID at 0x%"PRIx64"\n", + offset + PCI_CAP_LIST_ID); + return; + } + + if (cap_id != PCI_CAP_ID_EXP) { + rc = pci_device_cfg_read_u8(dev, &next_cap, + offset + PCI_CAP_LIST_NEXT); + if (rc) { + fprintf(stderr, "Failed reading next capability ID at 0x%"PRIx64"\n", + offset + PCI_CAP_LIST_NEXT); + return; + } + + offset = (pciaddr_t) next_cap; + continue; + } + + offset = 0x100; + do { + rc = pci_device_cfg_read_u32(dev, &pcie_cap_header, offset); + if (rc) { + fprintf(stderr, "Failed reading PCIe config header\n"); + return; + } + + pcie_cap_id = pcie_cap_header & 0xffff; + + if (pcie_cap_id != PCI_EXT_CAP_ID_DSN) { + offset = (pciaddr_t) pcie_cap_header >> 20; + continue; + } + + (void) pci_device_cfg_read_u32(dev, &dword_low, offset + 4); + (void) pci_device_cfg_read_u32(dev, &dword_high, offset + 8); + snprintf(info->serial_number, sizeof(info->serial_number), + "%02X%02X%02X%02X%02X%02X\n", + dword_high >> 24, (dword_high >> 16) & 0xff, + (dword_high >> 8) & 0xff, (dword_low >> 16) & 0xff, + (dword_low >> 8) & 0xff, dword_low & 0xff); + break; + } while (offset); + + break; + } +} + +static void get_pci_device_info(struct pci_device *dev, struct hba_info *info) +{ + char *unknown = "unknown"; + const char *vname; + const char *dname; + uint8_t revision; + + vname = pci_device_get_vendor_name(dev); + if (!vname) + vname = unknown; + + strncpy(info->manufacturer, vname, sizeof(info->manufacturer)); + + dname = pci_device_get_device_name(dev); + if (!dname) + dname = unknown; + + strncpy(info->model_description, dname, + sizeof(info->model_description)); + + pci_device_cfg_read_u8(dev, &revision, PCI_REVISION_ID); + snprintf(info->hardware_version, sizeof(info->hardware_version), + "%02x", revision); + + info->nports = 1; + + get_device_serial_number(dev, info); +} + +static void get_module_info(const char *pcidev, struct hba_info *info) +{ + char buf[1024]; + char *path; + int err; + + strncpy(info->driver_name, "Unknown", sizeof(info->driver_name)); + strncpy(info->driver_version, "Unknown", sizeof(info->driver_version)); + + err = asprintf(&path, "/sys/bus/pci/devices/%s/driver/module", pcidev); + if (err == -1) + return; + + sa_sys_read_line(path, "version", + info->driver_version, sizeof(info->driver_version)); + + err = readlink(path, buf, sizeof(buf) - 1); + free(path); + if (err == -1) + return; + + buf[err] = '\0'; + + if (strstr(buf, "module")) + strncpy(info->driver_name, + strstr(buf, "module") + strlen("module") + 1, + sizeof(info->driver_name)); + + return; +} + +struct hba_info *get_hbainfo_by_pcidev(const char *pcidev) +{ + struct pci_device_iterator *iterator; + struct pci_slot_match match; + struct pci_device *dev; + struct hba_info *info; + int rc; + + rc = pci_system_init(); + if (rc) + return NULL; + + info = calloc(1, sizeof(struct hba_info)); + if (!info) + return NULL; + + sscanf(pcidev, "%x:%x:%x.%x", &match.domain, &match.bus, &match.dev, &match.func); + + iterator = pci_slot_match_iterator_create(&match); + if (!iterator) { + free(info); + return NULL; + } + + for (;;) { + dev = pci_device_next(iterator); + if (!dev) + break; + get_pci_device_info(dev, info); + get_module_info(pcidev, info); + } + + free(iterator); + pci_system_cleanup(); + + return info; +} + +struct port_attributes *get_port_attribs(const char *host) +{ + struct port_attributes *pa; + char *path; + int err; + + err = asprintf(&path, "%s/%s", SYSFS_HOST_DIR, host); + if (err == -1) + return NULL; + + pa = calloc(1, sizeof(*pa)); + if (!pa) + goto free_path; + + strncpy(pa->device_name, host, sizeof(pa->device_name)); + + sa_sys_read_line(path, "symbolic_name", pa->symbolic_name, sizeof(pa->symbolic_name)); + sa_sys_read_line(path, "node_name", pa->node_name, sizeof(pa->node_name)); + sa_sys_read_line(path, "port_name", pa->port_name, sizeof(pa->port_name)); + sa_sys_read_line(path, "fabric_name", pa->fabric_name, sizeof(pa->fabric_name)); + sa_sys_read_line(path, "speed", pa->speed, sizeof(pa->speed)); + sa_sys_read_line(path, "supported_speeds", pa->supported_speeds, sizeof(pa->supported_speeds)); + sa_sys_read_line(path, "maxframe_size", pa->maxframe_size, sizeof(pa->maxframe_size)); + sa_sys_read_line(path, "port_id", pa->port_id, sizeof(pa->port_id)); + sa_sys_read_line(path, "port_state", pa->port_state, sizeof(pa->port_state)); + +free_path: + free(path); + + return pa; +} + +char *get_pci_dev_from_netdev(const char *netdev) +{ + char buf[1024]; + char *pcidev; + char *path; + char *cp; + int func; + int dom; + int bus; + int dev; + int ret; + + ret = asprintf(&path, "%s/%s/device", SYSFS_NET_DIR, netdev); + if (ret == -1) + return NULL; + + ret = readlink(path, buf, sizeof(buf) - 1); + free(path); + if (ret == -1) { + char realdev[256]; + char *subif; + size_t len; + + subif = strchr(netdev, '.'); + if (subif == NULL) + return NULL; + len = strlen(netdev) - strlen(subif); + strncpy(realdev, netdev, len); + if (realdev[len] != '\0') + realdev[len] = '\0'; + + ret = asprintf(&path, "%s/%s/lower_%s", SYSFS_NET_DIR, + netdev, realdev); + if (ret == -1) + return NULL; + + ret = readlink(path, buf, sizeof(buf) -1 ); + free(path); + + if (ret == -1) + return NULL; + } + + do { + cp = strrchr(buf, '/'); + if (!cp) + break; + + ret = sscanf(cp + 1, "%x:%x:%x.%x", &dom, &bus, &dev, &func); + if (ret == 4) + break; + + *cp = '\0'; + } while(cp && cp > buf); + + ret = asprintf(&pcidev, "%04x:%02x:%02x.%x", dom, bus, dev, func); + if (ret == -1) + return NULL; + + return pcidev; +} + +char *get_host_from_netdev(const char *netdev) +{ + struct dirent *dp; + char *host = NULL; + char *path = NULL; + DIR *dir; + int ret; + + ret = asprintf(&path, "%s/%s/ctlr_0/", SYSFS_NET_DIR, netdev); + if(ret == -1) + return NULL; + + dir = opendir(path); + free(path); + path = NULL; + + if (!dir) + return NULL; + + for (dp = readdir(dir); dp != NULL; dp = readdir(dir)) { + if (dp->d_name[0] == '.' && dp->d_name[1] == '\0') continue; + if (dp->d_name[1] == '.' && dp->d_name[2] == '\0') continue; + + host = strstr(dp->d_name, "host"); + if (host) { + struct stat sb; + + ret = asprintf(&path, "%s/%s/ctlr_0/%s/fc_host/%s", + SYSFS_NET_DIR, netdev, host, host); + if (ret == -1) + goto out_closedir; + + ret = stat(path, &sb); + free(path); + path = NULL; + + if (ret == -1) + host = NULL; + break; + + } + } + +out_closedir: + closedir(dir); + + return host ? strdup(host) : NULL; +} + +int get_number_of_adapters(void) +{ + struct dirent *dp; + int num = 0; + DIR *dir; + + dir = opendir(SYSFS_HOST_DIR); + if (!dir) + return errno; + + for (dp = readdir(dir); dp != NULL; dp = readdir(dir)) { + if (dp->d_name[0] == '.' && dp->d_name[1] == '\0') continue; + if (dp->d_name[1] == '.' && dp->d_name[2] == '\0') continue; + + if (strstr(dp->d_name, "host")) + num++; + + } + + closedir(dir); + + return num; +} -- 2.5.0
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor