This patch adds a new archive file that can be built into applications. This new library scans for both /sys/class/fcoe_ctlr/ and /sys/class/fcoe_fcf/ instances and populates libutil lists. These lists and the provided APIs can then be incorporated into applications to display FCoE information generated by the kernel.
Signed-off-by: Robert Love <[email protected]> Tested-by: Ross Brattain <[email protected]> --- Makefile.am | 5 + include/libopenfcoe.h | 110 ++++++++++++++++++++++ libopenfcoe.c | 244 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 357 insertions(+), 2 deletions(-) create mode 100644 include/libopenfcoe.h create mode 100644 libopenfcoe.c diff --git a/Makefile.am b/Makefile.am index 8f01599..1fcd8b7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -9,7 +9,7 @@ AM_CFLAGS = -Wall ## rules for building fcoeadm fcoeadm_SOURCES = fcoeadm.c fcoeadm_display.c -fcoeadm_LDADD = lib/libutil.a +fcoeadm_LDADD = lib/libutil.a libopenfcoe.a fcoeadm_CFLAGS = $(AM_CFLAGS) $(HBAAPI_CFLAGS) fcoeadm_LDFLAGS = $(AM_LDFLAGS) $(HBAAPI_LIBS) @@ -30,9 +30,10 @@ fipvlan_SOURCES = fipvlan.c fipvlan_LDADD = lib/libutil.a AUTOMAKE_OPTIONS=subdir-objects -noinst_LIBRARIES = lib/libutil.a +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 +libopenfcoe_a_SOURCES = libopenfcoe.c ## header files that need to be distributed noinst_HEADERS = fcoeadm_display.h fcoe_clif.h fcoemon.h \ diff --git a/include/libopenfcoe.h b/include/libopenfcoe.h new file mode 100644 index 0000000..d9992be --- /dev/null +++ b/include/libopenfcoe.h @@ -0,0 +1,110 @@ +/* + * Copyright(c) 2012 Intel Corporation. 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 _LIBOPENFCOE_H_ +#define _LIBOPENFCOE_H_ + +#include <net/if.h> +#include <net/if_arp.h> +#include <net/ethernet.h> + +#include "fcoemon_utils.h" +#include "fcoe_utils.h" + +#define MAC_ADDR_LEN 6 + +/* MAC_ADDR_STRLEN = strlen("00:11:22:33:44:55") */ +#define MAC_ADDR_STRLEN 17 + +enum fip_conn_type { + FIP_CONN_TYPE_UNKNOWN = 0, + FIP_CONN_TYPE_FABRIC, + FIP_CONN_TYPE_VN2VN, +}; + +static const struct sa_nameval fip_conn_type_table[] = { + { "Unknown", FIP_CONN_TYPE_UNKNOWN }, + { "Fabric", FIP_CONN_TYPE_FABRIC }, + { "VN2VN", FIP_CONN_TYPE_VN2VN }, + { NULL, 0 } +}; + +struct fcoe_ctlr_device { + /* Filesystem Information */ + int index; + char path[MAX_STR_LEN]; + char ifname[IFNAMSIZ]; + + /* Associations */ + struct sa_table fcfs; + + /* Attributes */ + u_int32_t fcf_dev_loss_tmo; + enum fip_conn_type mode; + u_int32_t lesb_link_fail; /* link failure count */ + u_int32_t lesb_vlink_fail; /* virtual link failure count */ + u_int32_t lesb_miss_fka; /* missing FIP keep-alive count */ + u_int32_t lesb_symb_err; /* symbol error during carrier count */ + u_int32_t lesb_err_block; /* errored block count */ + u_int32_t lesb_fcs_error; /* frame check sequence error count */ +}; + +/* fcf states */ +enum fcf_state { + FCOE_FCF_STATE_UNKNOWN = 0, + FCOE_FCF_STATE_DISCONNECTED, + FCOE_FCF_STATE_CONNECTED, + FCOE_FCF_STATE_DELETED, +}; + +static const struct sa_nameval fcf_state_table[] = { + { "Unknown", FCOE_FCF_STATE_UNKNOWN }, + { "Disconnected", FCOE_FCF_STATE_DISCONNECTED }, + { "Connected", FCOE_FCF_STATE_CONNECTED }, + { "Deleted", FCOE_FCF_STATE_DELETED }, + { NULL, 0 } +}; + +struct fcoe_fcf_device { + /* Filesystem Information */ + int index; + char path[MAX_STR_LEN]; + + /* Attributes */ + enum fcf_state state; + u_int32_t dev_loss_tmo; + u_int64_t fabric_name; + u_int64_t switch_name; + u_int32_t fc_map; + u_int32_t vfid; /* u16 in kernel */ + u_int8_t mac[MAC_ADDR_LEN]; + u_int32_t priority; /* u8 in kernel */ + u_int32_t fka_period; + u_int32_t selected; /* u8 in kernel */ + u_int32_t vlan_id; /* u16 in kernel */ +}; + +void read_fcoe_ctlr(struct sa_table *ctlrs); +void print_fcoe_ctlr_device(void *ep, void *arg); +void free_fcoe_ctlr_device(void *ep, void *arg); + +int mac2str(const u_int8_t *mac, char *dst, size_t size); +int str2mac(const char *src, u_int8_t *mac, size_t size); + +#endif /* _LIBOPENFCOE_H_ */ diff --git a/libopenfcoe.c b/libopenfcoe.c new file mode 100644 index 0000000..9c4cfd9 --- /dev/null +++ b/libopenfcoe.c @@ -0,0 +1,244 @@ +/* + * Copyright(c) 2012-2013 Intel Corporation. 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 + */ + +#include "libopenfcoe.h" + +#define SYSFS_HOST_DIR "/sys/class/fc_host" +#define SYSFS_HBA_DIR "/sys/class/net" + +int mac2str(const u_int8_t *mac, char *dst, size_t size) +{ + if (dst && size > MAC_ADDR_STRLEN) { + snprintf(dst, size, "%02X:%02X:%02X:%02X:%02X:%02X", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + return 0; + } + return -1; +} + +int str2mac(const char *src, u_int8_t *mac, size_t size) +{ + int i = 0; + int rc = -1; + + if (size < 6) + goto out_err; + + if (!src) + goto out_err; + + if (strlen(src) != MAC_ADDR_STRLEN) + goto out_err; + + memset(mac, 0, size); + for (i = 0; i < 6; i++, mac++) + if (1 != sscanf(&src[i * 3], "%02hhX", mac)) + goto out_err; + rc = 0; +out_err: + return rc; +} + +static int add_fcoe_fcf_device(struct dirent *dp, void *arg) +{ + struct fcoe_ctlr_device *ctlr = (struct fcoe_ctlr_device *)arg; + struct fcoe_fcf_device *fcf; + + if (!strstr(dp->d_name, "fcf") || + (!strcmp(dp->d_name, "fcf_dev_loss_tmo"))) + return 0; + + fcf = malloc(sizeof(struct fcoe_fcf_device)); + if (!fcf) + return -ENOMEM; + + memset(fcf, 0, sizeof(struct fcoe_fcf_device)); + + /* Save the path */ + snprintf(fcf->path, sizeof(fcf->path), + "%s/%s", ctlr->path, dp->d_name); + + /* Use the index from the logical enumeration */ + fcf->index = atoi(dp->d_name + sizeof("fcf_") - 1); + + /* Save the fcf in the fcport's table */ + if (sa_table_insert(&ctlr->fcfs, fcf->index, + fcf) < 0) { + fprintf(stderr, "%s: insert of fcf %d failed\n", + __func__, fcf->index); + goto fail; + } + + return 0; + +fail: + free(fcf); + return -ENOENT; +} + +static void read_fcoe_fcf_device(void *ep, void *arg) +{ + struct fcoe_fcf_device *fcf = (struct fcoe_fcf_device *)ep; + char buf[MAX_STR_LEN]; + + sa_sys_read_line(fcf->path, "state", buf, sizeof(buf)); + sa_enum_encode(fcf_state_table, buf, &fcf->state); + sa_sys_read_u32(fcf->path, "dev_loss_tmo", &fcf->dev_loss_tmo); + sa_sys_read_u64(fcf->path, "fabric_name", &fcf->fabric_name); + sa_sys_read_u64(fcf->path, "switch_name", &fcf->switch_name); + sa_sys_read_u32(fcf->path, "fc_map", &fcf->fc_map); + sa_sys_read_u32(fcf->path, "vfid", &fcf->vfid); + + sa_sys_read_line(fcf->path, "mac", buf, MAX_STR_LEN); + str2mac(buf, &fcf->mac[0], MAC_ADDR_LEN); + + sa_sys_read_u32(fcf->path, "priority", &fcf->priority); + sa_sys_read_u32(fcf->path, "fka_period", &fcf->fka_period); + sa_sys_read_u32(fcf->path, "selected", &fcf->selected); + sa_sys_read_u32(fcf->path, "vlan_id", &fcf->vlan_id); +} + +void read_fcoe_fcf(void *ep, void *arg) +{ + struct fcoe_ctlr_device *ctlr = (struct fcoe_ctlr_device *)ep; + + /* Iterate through the ctlr and add any fcfs */ + sa_dir_read(ctlr->path, add_fcoe_fcf_device, ctlr); + + /* Populate each fabric */ + sa_table_iterate(&ctlr->fcfs, read_fcoe_fcf_device, NULL); +} + +void free_fcoe_fcf_device(void *ep, void *arg) +{ + struct fcoe_fcf_device *fcf = (struct fcoe_fcf_device *)ep; + + free(fcf); +} + +#define SYSFS_MOUNT "/sys" +#define FCOE_CTLR_DEVICE_DIR SYSFS_MOUNT "/bus/fcoe/devices/" + +static int find_fchost(struct dirent *dp, void *arg) +{ + char *fchost = arg; + + if (strstr(dp->d_name, "host")) { + strncpy(fchost, dp->d_name, MAX_STR_LEN); + return 1; + } + + return 0; +} + +int read_fcoe_ctlr_device(struct dirent *dp, void *arg) +{ + struct sa_table *ctlrs = arg; + struct fcoe_ctlr_device *ctlr; + char buf[MAX_STR_LEN]; + char lesb_path[MAX_STR_LEN]; + char hpath[MAX_STR_LEN]; + char fchost[MAX_STR_LEN]; + char *cp, *ifname; + int rc; + + if (strncmp(dp->d_name, "ctlr_", 5)) + return 0; + + ctlr = malloc(sizeof(struct fcoe_ctlr_device)); + if (!ctlr) + return 0; /* Must return 0 or loop will break */ + + memset(ctlr, 0, sizeof(struct fcoe_ctlr_device)); + sa_table_init(&ctlr->fcfs); + + /* Save the path */ + snprintf(ctlr->path, sizeof(ctlr->path), + FCOE_CTLR_DEVICE_DIR "%s", dp->d_name); + + /* Use the index from the logical enumeration */ + ctlr->index = atoi(dp->d_name + sizeof("ctlr_") - 1); + + rc = sa_dir_read(ctlr->path, find_fchost, fchost); + if (!rc) + goto fail; + + sprintf(hpath, "%s/%s/", SYSFS_FCHOST, fchost); + + rc = sa_sys_read_line(hpath, "symbolic_name", buf, sizeof(buf)); + + /* Skip the HBA if it isn't Open-FCoE */ + cp = strstr(buf, " over "); + if (!cp) + goto fail; + + ifname = get_ifname_from_symbolic_name(buf); + strncpy(ctlr->ifname, ifname, IFNAMSIZ-1); + + /* Get fcf device loss timeout */ + sa_sys_read_u32(ctlr->path, "fcf_dev_loss_tmo", + &ctlr->fcf_dev_loss_tmo); + + sa_sys_read_line(ctlr->path, "mode", buf, sizeof(buf)); + sa_enum_encode(fip_conn_type_table, buf, &ctlr->mode); + + snprintf(lesb_path, sizeof(lesb_path), "%s/lesb/", ctlr->path); + + /* Get LESB statistics */ + sa_sys_read_u32(lesb_path, "link_fail", + &ctlr->lesb_link_fail); + sa_sys_read_u32(lesb_path, "vlink_fail", + &ctlr->lesb_vlink_fail); + sa_sys_read_u32(lesb_path, "miss_fka", + &ctlr->lesb_miss_fka); + sa_sys_read_u32(lesb_path, "symb_err", + &ctlr->lesb_symb_err); + sa_sys_read_u32(lesb_path, "err_block", + &ctlr->lesb_err_block); + sa_sys_read_u32(lesb_path, "fcs_error", + &ctlr->lesb_fcs_error); + + /* Save the ctlr in the supplied table */ + if (sa_table_insert(ctlrs, ctlr->index, ctlr) < 0) { + fprintf(stderr, "%s: insert of ctlr %d failed\n", + __func__, ctlr->index); + goto fail; + } + + return 0; + +fail: + free(ctlr); + return -ENOENT; +} + +void read_fcoe_ctlr(struct sa_table *ctlrs) +{ + sa_dir_read(FCOE_CTLR_DEVICE_DIR, read_fcoe_ctlr_device, ctlrs); + sa_table_iterate(ctlrs, read_fcoe_fcf, NULL); +} + +void free_fcoe_ctlr_device(void *ep, void *arg) +{ + struct fcoe_ctlr_device *ctlr = (struct fcoe_ctlr_device *)ep; + + sa_table_iterate(&ctlr->fcfs, free_fcoe_fcf_device, NULL); + + free(ctlr); +} _______________________________________________ devel mailing list [email protected] https://lists.open-fcoe.org/mailman/listinfo/devel
