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

Reply via email to