File 0016-fcping-Convert-fcping-to-internal-sysfs-based-implem.patch of Package fcoe-utils

From a07b022bc5b42252fa71953e3df1c66a25dba926 Mon Sep 17 00:00:00 2001
Message-Id: <a07b022bc5b42252fa71953e3df1c66a25dba926.1439372158.git.jthumshirn@suse.de>
In-Reply-To: <cover.1439372158.git.jthumshirn@suse.de>
References: <cover.1439372158.git.jthumshirn@suse.de>
From: Johannes Thumshirn <jthumshirn@suse.de>
Date: Mon, 10 Aug 2015 12:37:22 +0200
Subject: [PATCH 8/9] fcping: Convert fcping to internal sysfs based
 implementation

Convert fcping to internal sysfs based implementation as well, so all of
libHBAAPI is gone now.

Signed-off-by: Johannes Thumshirn <jthumshirn@suse.de>
---
 Makefile.am         |   2 +-
 fcping.c            | 183 +++++++++++++++++-----------------------------------
 include/sysfs_hba.h |  10 +++
 lib/sysfs_hba.c     | 111 +++++++++++++++++++++++++++++++
 4 files changed, 181 insertions(+), 125 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 59c197d..42f9200 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -19,7 +19,7 @@ fcoemon_CFLAGS = $(AM_CFLAGS) $(DCBD_CFLAGS)
 
 ## rules for building fcping
 fcping_SOURCES = fcping.c
-fcping_LDADD = lib/libutil.a $(HBAAPI_LIBS) -lrt
+fcping_LDADD = lib/libutil.a $(HBAAPI_LIBS) $(PCIACCESS_LIBS) -lrt
 fcping_CFLAGS = $(AM_CFLAGS) $(HBAAPI_CFLAGS)
 
 ## rules for building fipvlan
diff --git a/fcping.c b/fcping.c
index 399b778..89988f4 100644
--- a/fcping.c
+++ b/fcping.c
@@ -42,8 +42,6 @@
 #include <sys/time.h>
 #include <net/ethernet.h>
 #include <netinet/ether.h>
-#include <hbaapi.h>
-#include <vendorhbaapi.h>
 #include <linux/types.h>
 #include <linux/bsg.h>
 #include "net_types.h"
@@ -56,6 +54,8 @@ typedef uint8_t u8;
 #include "fc_els.h"
 #include "scsi_bsg_fc.h"
 
+#include "sysfs_hba.h"
+
 static const char *cmdname;
 
 #define FC_MAX_PAYLOAD  2112UL	/* Max FC payload */
@@ -116,19 +116,12 @@ static uint32_t fp_interval = FP_DEF_INTVL * 1000; /* in milliseconds */
 static int fp_quiet;
 static int fp_hex;
 static char *fp_hba;	/* name of interface to be used */
-static int fp_hba_type;
-#define FP_HBA_FCID_TYPE	1
-#define FP_HBA_WWPN_TYPE	2
-#define FP_HBA_HOST_TYPE	3
-#define FP_HBA_ETH_TYPE		4
 static char fp_dev[64];
 static int fp_fd;	/* file descriptor for openfc ioctls */
 static void *fp_buf;	/* sending buffer */
 static int fp_debug;
-
-static HBA_HANDLE hba_handle;
-static HBA_ADAPTERATTRIBUTES hba_attrs;
-static HBA_PORTATTRIBUTES port_attrs;
+static char *host;;
+static struct port_attributes *port_attrs;
 
 struct fp_stats {
 	uint32_t fp_tx_frames;
@@ -471,17 +464,17 @@ fp_options(int argc, char *argv[])
 static int
 fp_find_hba(void)
 {
-	HBA_STATUS retval;
-	HBA_UINT32 hba_cnt;
-	HBA_UINT32 fcid = 0;
 	struct stat statbuf;
-	char namebuf[1028];
 	char hba_dir[256];
 	fc_wwn_t wwn = 0;
-	HBA_WWN wwpn;
+	struct hba_wwn wwpn;
 	char *endptr;
-	unsigned int i;
-	int found = 0;
+	uint32_t fcid;
+	int hba_cnt;
+
+	hba_cnt = get_number_of_adapters();
+	if (!hba_cnt)
+		SA_LOG_EXIT("No FCoE interfaces created");
 
 	/*
 	 * Parse HBA spec. if there is one.
@@ -494,15 +487,14 @@ fp_find_hba(void)
 	 *    mac address xx:xx:xx:xx:xx:xx
 	 *    otherwise, try parsing as a wwn and match that.
 	 */
-
 	snprintf(hba_dir, sizeof(hba_dir), SYSFS_HBA_DIR "/%s", fp_hba);
 	if (!stat(hba_dir, &statbuf)) {
-		fp_hba_type = FP_HBA_ETH_TYPE;
+		host = get_host_from_netdev(fp_hba);
 	} else if (strstr(fp_hba, "host") == fp_hba) {
-		i = strtoul(fp_hba + 4, &endptr, 10);
+		(void) strtoul(fp_hba + strlen("host"), &endptr, 10);
 		if (*endptr != '\0')
 			SA_LOG_EXIT("invalid hba name %s", fp_hba);
-		fp_hba_type = FP_HBA_HOST_TYPE;
+		host = strdup(fp_hba);
 	} else if (strstr(fp_hba, ":")) {
 		if (strlen(fp_hba) == strlen("xx:yy:aa:bb:cc:dd:ee:ff")) {
 			fc_wwn_t wwn1;
@@ -518,84 +510,35 @@ fp_find_hba(void)
 			SA_LOG_EXIT("invalid WWPN or MAC address %s", fp_hba);
 		}
 		hton64(wwpn.wwn, wwn);
-		fp_hba_type = FP_HBA_WWPN_TYPE;
+		host = get_host_by_wwpn(wwpn);
 	} else {
 		wwn = strtoull(fp_hba, &endptr, 16);
 		if (wwn < 0x1000000) {
 			fcid = wwn;
-			fp_hba_type = FP_HBA_FCID_TYPE;
+			host = get_host_by_fcid(fcid);
 		} else {
 			if (*endptr != '\0')
 				SA_LOG_EXIT("unsupported hba name");
 			wwn = fp_parse_wwn(fp_hba, "HBA", 2, 0);
 			hton64(wwpn.wwn, wwn);
-			fp_hba_type = FP_HBA_WWPN_TYPE;
+			host = get_host_by_wwpn(wwpn);
 		}
 	}
 
-	hba_cnt = HBA_GetNumberOfAdapters();
-	if (!hba_cnt)
-		SA_LOG_EXIT("No FCoE interfaces created");
-
-	for (i = 0; i < hba_cnt; i++) {
-		retval = HBA_GetAdapterName(i, namebuf);
-		if (retval != HBA_STATUS_OK) {
-			SA_LOG("HBA_GetAdapterName"
-			       " failed, retval=%d", retval);
-			continue;
-		}
-
-		hba_handle = HBA_OpenAdapter(namebuf);
-		if (!hba_handle) {
-			SA_LOG("HBA_OpenAdapter failed");
-			continue;
-		}
-
-		retval = HBA_GetAdapterAttributes(hba_handle, &hba_attrs);
-		if (retval != HBA_STATUS_OK) {
-			SA_LOG("HBA_GetAdapterAttributes"
-			       " failed, retval=%d", retval);
-			continue;
-		}
-
-		retval = HBA_GetAdapterPortAttributes(
-			hba_handle, 0, &port_attrs);
-		if (retval != HBA_STATUS_OK) {
-			SA_LOG("HBA_GetAdapterPortAttributes"
-			       " failed, retval=%d", retval);
-			continue;
-		}
+	if (!host) {
+		SA_LOG("FCoE interface %s not found", fp_hba);
+		return 0;
+	}
 
-		switch (fp_hba_type) {
-		case FP_HBA_FCID_TYPE:
-			if (port_attrs.PortFcId != fcid)
-				continue;
-			break;
-		case FP_HBA_WWPN_TYPE:
-			if (memcmp(&port_attrs.PortWWN, &wwpn, sizeof(wwpn)))
-				continue;
-			break;
-		case FP_HBA_HOST_TYPE:
-			if (!strstr(port_attrs.OSDeviceName, fp_hba))
-				continue;
-			break;
-		default:
-			if (check_symbolic_name_for_interface(
-				    port_attrs.PortSymbolicName,
-				    fp_hba))
-				continue;
-			break;
-		}
+	snprintf(fp_dev, sizeof(fp_dev), "fc_%s", host);
 
-		snprintf(fp_dev, sizeof(fp_dev),
-			 "fc_%s", port_attrs.OSDeviceName);
-		found = 1;
-		break;
+	port_attrs = get_port_attribs(host);
+	if (!port_attrs) {
+		free(host);
+		return 0;
 	}
-	if (!found)
-		SA_LOG("FCoE interface %s not found", fp_hba);
 
-	return found;
+	return 1;
 }
 
 static void
@@ -728,32 +671,10 @@ static int fp_lookup_target(void)
  */
 static uint32_t fp_get_max_data_len(fc_fid_t fcid)
 {
-	HBA_STATUS retval;
-	HBA_PORTATTRIBUTES rport_attrs;
-	unsigned int i;
-	uint32_t dlen = 0;
-
-	if (!hba_handle) {
-		SA_LOG("%s: Invalid handle! HBA_OpenAdapter failed?", fp_dev);
-		goto out;
-	}
-
-	/* locate targets */
-	for (i = 0; i < port_attrs.NumberofDiscoveredPorts; i++) {
-		retval = HBA_GetDiscoveredPortAttributes(hba_handle, 0, i,
-							 &rport_attrs);
-		if (retval != HBA_STATUS_OK) {
-			SA_LOG("HBA_GetDiscoveredPortAttributes() "
-			       "failed for HBA %s on target index %d, "
-			       "status=%d\n", fp_dev, i, retval);
-			continue;
-		}
-		if (rport_attrs.PortFcId == fcid) {
-			dlen = rport_attrs.PortMaxFrameSize - FP_LEN_ECHO;
-			goto out;
-		}
-
-	}
+	struct port_attributes *rport_attrs;
+	uint32_t dlen = FP_LEN_DEF;
+	uint32_t maxframe_size;
+	char *rport;
 
 	/* not found from disovered ports, if it's one of the
 	 * WKA from FC-LS Table 30, use FC_MAX_PAYLOAD */
@@ -761,7 +682,22 @@ static uint32_t fp_get_max_data_len(fc_fid_t fcid)
 		dlen = FP_LEN_MAX;
 		goto out;
 	}
-	dlen = FP_LEN_DEF;
+
+	rport = get_rport_by_fcid(fcid);
+	if (!rport)
+		goto out;
+
+	rport_attrs = get_rport_attribs(rport);
+	if (!rport_attrs)
+		goto free_rport;
+
+	maxframe_size = strtoul(rport_attrs->maxframe_size, NULL, 16);
+	dlen = maxframe_size - FP_LEN_ECHO;
+
+	free(rport_attrs);
+free_rport:
+	free(rport);
+
 out:
 	/* returns maximum allowed ECHO data length, excluding the 4
 	 * bytes ECHO command in the payload */
@@ -790,6 +726,7 @@ static void fp_check_data_len(void)
 	uint32_t dlen = 0;
 	uint32_t flen = 0;
 	uint32_t plen = FP_LEN_DEF;
+	uint32_t maxframe_size;
 
 	/* find out maximum payload supported by the fabric */
 	flen = fp_get_max_data_len(FC_WKA_FABRIC_CONTROLLER);
@@ -804,8 +741,13 @@ static void fp_check_data_len(void)
 	if (!dlen)
 		dlen = FP_LEN_DEF;
 
-	sid = port_attrs.PortFcId;
-	slen = port_attrs.PortMaxFrameSize - FP_LEN_ECHO;
+
+	maxframe_size = strtoul(port_attrs->maxframe_size, NULL, 16);
+	sid = strtoul(port_attrs->port_id, NULL, 16);
+
+	free(port_attrs);
+
+	slen = maxframe_size - FP_LEN_ECHO;
 	plen = MIN(flen, MIN(slen, dlen));
 
 	printf("Maximum ECHO data allowed by the Fabric (0x%06x) : %d bytes.\n"
@@ -1020,8 +962,8 @@ static void fp_start(void)
 	sigaction(SIGQUIT, &act, NULL);		/* Signal 3: Ctrl-\ */
 	sigaction(SIGINT,  &act, NULL);		/* Signal 2: Ctrl-C */
 
-	printf("Sending FC ELS ECHO from 0x%X (%s) to 0x%X:\n",
-	       port_attrs.PortFcId, fp_dev, fp_did);
+	printf("Sending FC ELS ECHO from %s (%s) to 0x%X:\n",
+	       port_attrs->port_id, fp_dev, fp_did);
 
 	for (i = 0; fp_count == -1 || i < fp_count; i++) {
 		rc = fp_send_ping();
@@ -1045,11 +987,6 @@ int main(int argc, char *argv[])
 	int rc = 1;
 
 	fp_options(argc, argv);
-
-	if (HBA_LoadLibrary() != HBA_STATUS_OK)
-		SA_LOG_ERR_EXIT(errno, "HBA_LoadLibrary failed");
-
-	hba_handle = 0;
 	if (fp_find_hba()) {
 		sprintf(bsg_dev, "/dev/bsg/%s", fp_dev);
 		fp_fd = open(bsg_dev, O_RDWR);
@@ -1064,12 +1001,10 @@ int main(int argc, char *argv[])
 			fp_report();
 			rc = 0;
 		}
+		free(port_attrs);
+		free(host);
 		close(fp_fd);
 	}
 
-	if (hba_handle)
-		HBA_CloseAdapter(hba_handle);
-
-	HBA_FreeLibrary();
 	return rc;
 }
diff --git a/include/sysfs_hba.h b/include/sysfs_hba.h
index 170935c..4efacd8 100644
--- a/include/sysfs_hba.h
+++ b/include/sysfs_hba.h
@@ -95,6 +95,13 @@ struct port_statistics {
 	uint64_t fcp_output_megabytes;
 };
 
+struct hba_wwn {
+	union {
+		uint8_t wwn[8];
+		uint64_t wwn64;
+	};
+};
+
 int get_number_of_adapters(void);
 struct hba_info *get_hbainfo_by_pcidev(const char *pcidev);
 struct port_statistics *get_port_statistics(const char *host);
@@ -104,5 +111,8 @@ struct port_attributes *get_rport_attribs(const char *rport);
 struct port_attributes *get_rport_attribs_by_device(char *path);
 char *get_pci_dev_from_netdev(const char *netdev);
 char *get_host_from_netdev(const char *netdev);
+char *get_host_by_wwpn(struct hba_wwn wwn);
+char *get_host_by_fcid(uint32_t fcid);
+char *get_rport_by_fcid(uint32_t fcid);
 
 #endif /* _SYSFS_HBA_H */
diff --git a/lib/sysfs_hba.c b/lib/sysfs_hba.c
index 7ecd399..6bff2de 100644
--- a/lib/sysfs_hba.c
+++ b/lib/sysfs_hba.c
@@ -33,11 +33,24 @@
 
 #include "sysfs_hba.h"
 #include "fcoemon_utils.h"
+#include "net_types.h"
 
 #define SYSFS_HOST_DIR		"/sys/class/fc_host"
 #define SYSFS_NET_DIR		"/sys/class/net"
 #define SYSFS_RPORT_DIR		"/sys/class/fc_remote_ports"
 
+#define hton64(p, v)					\
+	do {						\
+		p[0] = (u_char) ((v) >> 56) & 0xFF;	\
+		p[1] = (u_char) ((v) >> 48) & 0xFF;	\
+		p[2] = (u_char) ((v) >> 40) & 0xFF;	\
+		p[3] = (u_char) ((v) >> 32) & 0xFF;	\
+		p[4] = (u_char) ((v) >> 24) & 0xFF;	\
+		p[5] = (u_char) ((v) >> 16) & 0xFF;	\
+		p[6] = (u_char) ((v) >> 8) & 0xFF;	\
+		p[7] = (u_char) (v) & 0xFF;		\
+	} while (0)
+
 struct port_attributes *get_port_attribs_by_device(char *path)
 {
 	char link[1024];
@@ -417,6 +430,104 @@ char *get_pci_dev_from_netdev(const char *netdev)
 	return pcidev;
 }
 
+char *get_host_by_wwpn(struct hba_wwn wwn)
+{
+	struct dirent *dp;
+	DIR *dir;
+	char *host = NULL;
+	char path[1024];
+	uint64_t port_name;
+	struct hba_wwn port_wwn;
+
+	dir = opendir(SYSFS_HOST_DIR);
+	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;
+
+		snprintf(path, sizeof(path), "%s/%s", SYSFS_HOST_DIR,
+			 dp->d_name);
+
+		sa_sys_read_u64(path, "port_name", &port_name);
+		hton64(port_wwn.wwn, port_name);
+				if (memcmp((void *)&port_wwn, &wwn, sizeof(struct hba_wwn)))
+				continue;
+
+		host = strdup(dp->d_name);
+		break;
+	}
+
+	closedir(dir);
+
+	return host;;
+}
+
+char *get_host_by_fcid(uint32_t fcid)
+{
+	struct dirent *dp;
+	DIR *dir;
+	char *host = NULL;
+	char path[1024];
+	uint32_t port_id;
+
+	dir = opendir(SYSFS_HOST_DIR);
+	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;
+
+		snprintf(path, sizeof(path), "%s/%s", SYSFS_HOST_DIR,
+			dp->d_name);
+
+		sa_sys_read_u32(path, "port_id", &port_id);
+		if (port_id != fcid)
+			continue;
+
+		host = strdup(dp->d_name);
+		break;
+	}
+
+	closedir(dir);
+
+	return host;
+}
+
+char *get_rport_by_fcid(uint32_t fcid)
+{
+	struct dirent *dp;
+	DIR *dir;
+	char *rport = NULL;
+	char path[1024];
+	uint32_t port_id;
+
+	dir = opendir(SYSFS_RPORT_DIR);
+	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;
+
+		snprintf(path, sizeof(path), "%s/%s", SYSFS_RPORT_DIR,
+			dp->d_name);
+
+		sa_sys_read_u32(path, "port_id", &port_id);
+		if (port_id != fcid)
+			continue;
+
+		rport = strdup(dp->d_name);
+		break;
+	}
+
+	closedir(dir);
+
+	return rport;
+}
+
 char *get_host_from_netdev(const char *netdev)
 {
 	struct dirent *dp;
-- 
2.4.6

openSUSE Build Service is sponsored by