Blame libopenfcoe.c

Packit Service bca4e3
/*
Packit Service bca4e3
 * Copyright(c) 2012-2013 Intel Corporation. All rights reserved.
Packit Service bca4e3
 *
Packit Service bca4e3
 * This program is free software; you can redistribute it and/or modify it
Packit Service bca4e3
 * under the terms and conditions of the GNU General Public License,
Packit Service bca4e3
 * version 2, as published by the Free Software Foundation.
Packit Service bca4e3
 *
Packit Service bca4e3
 * This program is distributed in the hope it will be useful, but WITHOUT
Packit Service bca4e3
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
Packit Service bca4e3
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
Packit Service bca4e3
 * more details.
Packit Service bca4e3
 *
Packit Service bca4e3
 * You should have received a copy of the GNU General Public License along with
Packit Service bca4e3
 * this program; if not, write to the Free Software Foundation, Inc.,
Packit Service bca4e3
 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
Packit Service bca4e3
 *
Packit Service bca4e3
 * Maintained at www.Open-FCoE.org
Packit Service bca4e3
 */
Packit Service bca4e3
Packit Service bca4e3
#include "libopenfcoe.h"
Packit Service bca4e3
Packit Service bca4e3
#define SYSFS_HOST_DIR	   "/sys/class/fc_host"
Packit Service bca4e3
#define SYSFS_HBA_DIR	   "/sys/class/net"
Packit Service bca4e3
Packit Service bca4e3
int mac2str(const u_int8_t *mac, char *dst, size_t size)
Packit Service bca4e3
{
Packit Service bca4e3
	if (dst && size > MAC_ADDR_STRLEN) {
Packit Service bca4e3
		snprintf(dst, size, "%02X:%02X:%02X:%02X:%02X:%02X",
Packit Service bca4e3
			 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
Packit Service bca4e3
		return 0;
Packit Service bca4e3
	}
Packit Service bca4e3
	return -1;
Packit Service bca4e3
}
Packit Service bca4e3
Packit Service bca4e3
int str2mac(const char *src, u_int8_t *mac, size_t size)
Packit Service bca4e3
{
Packit Service bca4e3
	int i = 0;
Packit Service bca4e3
	int rc = -1;
Packit Service bca4e3
Packit Service bca4e3
	if (size < 6)
Packit Service bca4e3
		goto out_err;
Packit Service bca4e3
Packit Service bca4e3
	if (!src)
Packit Service bca4e3
		goto out_err;
Packit Service bca4e3
Packit Service bca4e3
	if (strlen(src) != MAC_ADDR_STRLEN)
Packit Service bca4e3
		goto out_err;
Packit Service bca4e3
Packit Service bca4e3
	memset(mac, 0, size);
Packit Service bca4e3
	for (i = 0; i < 6; i++, mac++)
Packit Service bca4e3
		if (1 != sscanf(&src[i * 3], "%02hhX", mac))
Packit Service bca4e3
			goto out_err;
Packit Service bca4e3
	rc = 0;
Packit Service bca4e3
out_err:
Packit Service bca4e3
	return rc;
Packit Service bca4e3
}
Packit Service bca4e3
Packit Service bca4e3
static char *safe_makepath(char *path, size_t path_sz,
Packit Service bca4e3
		char *dname, char *fname)
Packit Service bca4e3
{
Packit Service bca4e3
	size_t dsz = sizeof(dname);
Packit Service bca4e3
	size_t fsz = strlen(fname);
Packit Service bca4e3
	char *cp = path;
Packit Service bca4e3
Packit Service bca4e3
	if ((dsz + fsz + 2) > path_sz) {
Packit Service bca4e3
		fprintf(stderr,
Packit Service bca4e3
			"error: no room to expand pathname (%d+%d > %d)\n",
Packit Service bca4e3
			(int)dsz, (int)fsz, (int)path_sz);
Packit Service bca4e3
		return NULL;
Packit Service bca4e3
	}
Packit Service bca4e3
Packit Service bca4e3
	memcpy(cp, dname, dsz);
Packit Service bca4e3
	cp += dsz;
Packit Service bca4e3
Packit Service bca4e3
	*cp++ = '/';
Packit Service bca4e3
Packit Service bca4e3
	memcpy(cp, fname, fsz);
Packit Service bca4e3
	cp += fsz;
Packit Service bca4e3
Packit Service bca4e3
	*cp = '\0';
Packit Service bca4e3
Packit Service bca4e3
	return path;
Packit Service bca4e3
}
Packit Service bca4e3
Packit Service bca4e3
static int add_fcoe_fcf_device(struct dirent *dp, void *arg)
Packit Service bca4e3
{
Packit Service bca4e3
	struct fcoe_ctlr_device *ctlr = (struct fcoe_ctlr_device *)arg;
Packit Service bca4e3
	struct fcoe_fcf_device *fcf;
Packit Service bca4e3
Packit Service bca4e3
	if (!strstr(dp->d_name, "fcf") ||
Packit Service bca4e3
	    (!strcmp(dp->d_name, "fcf_dev_loss_tmo")))
Packit Service bca4e3
		return 0;
Packit Service bca4e3
Packit Service bca4e3
	fcf = malloc(sizeof(struct fcoe_fcf_device));
Packit Service bca4e3
	if (!fcf)
Packit Service bca4e3
		return -ENOMEM;
Packit Service bca4e3
Packit Service bca4e3
	memset(fcf, 0, sizeof(struct fcoe_fcf_device));
Packit Service bca4e3
Packit Service bca4e3
	/* Save the path */
Packit Service bca4e3
	if (safe_makepath(fcf->path, sizeof(fcf->path),
Packit Service bca4e3
				ctlr->path, dp->d_name) == NULL)
Packit Service bca4e3
		goto fail;
Packit Service bca4e3
Packit Service bca4e3
	/* Use the index from the logical enumeration */
Packit Service bca4e3
	fcf->index = atoi(dp->d_name + sizeof("fcf_") - 1);
Packit Service bca4e3
Packit Service bca4e3
	/* Save the fcf in the fcport's table */
Packit Service bca4e3
	if (sa_table_insert(&ctlr->fcfs, fcf->index,
Packit Service bca4e3
			    fcf) < 0) {
Packit Service bca4e3
		fprintf(stderr, "%s: insert of fcf %d failed\n",
Packit Service bca4e3
			__func__, fcf->index);
Packit Service bca4e3
		goto fail;
Packit Service bca4e3
	}
Packit Service bca4e3
Packit Service bca4e3
	return 0;
Packit Service bca4e3
Packit Service bca4e3
fail:
Packit Service bca4e3
	free(fcf);
Packit Service bca4e3
	return -ENOENT;
Packit Service bca4e3
}
Packit Service bca4e3
Packit Service bca4e3
static void read_fcoe_fcf_device(void *ep, UNUSED void *arg)
Packit Service bca4e3
{
Packit Service bca4e3
	struct fcoe_fcf_device *fcf = (struct fcoe_fcf_device *)ep;
Packit Service bca4e3
	char buf[MAX_STR_LEN];
Packit Service bca4e3
Packit Service bca4e3
	sa_sys_read_line(fcf->path, "state", buf, sizeof(buf));
Packit Service bca4e3
	sa_enum_encode(fcf_state_table, buf, &fcf->state);
Packit Service bca4e3
	sa_sys_read_u32(fcf->path, "dev_loss_tmo", &fcf->dev_loss_tmo);
Packit Service bca4e3
	sa_sys_read_u64(fcf->path, "fabric_name", &fcf->fabric_name);
Packit Service bca4e3
	sa_sys_read_u64(fcf->path, "switch_name", &fcf->switch_name);
Packit Service bca4e3
	sa_sys_read_u32(fcf->path, "fc_map", &fcf->fc_map);
Packit Service bca4e3
	sa_sys_read_u32(fcf->path, "vfid", &fcf->vfid);
Packit Service bca4e3
Packit Service bca4e3
	sa_sys_read_line(fcf->path, "mac", buf, MAX_STR_LEN);
Packit Service bca4e3
	str2mac(buf, &fcf->mac[0], MAC_ADDR_LEN);
Packit Service bca4e3
Packit Service bca4e3
	sa_sys_read_u32(fcf->path, "priority", &fcf->priority);
Packit Service bca4e3
	sa_sys_read_u32(fcf->path, "fka_period", &fcf->fka_period);
Packit Service bca4e3
	sa_sys_read_u32(fcf->path, "selected", &fcf->selected);
Packit Service bca4e3
	sa_sys_read_u32(fcf->path, "vlan_id", &fcf->vlan_id);
Packit Service bca4e3
}
Packit Service bca4e3
Packit Service bca4e3
static void read_fcoe_fcf(void *ep, UNUSED void *arg)
Packit Service bca4e3
{
Packit Service bca4e3
	struct fcoe_ctlr_device *ctlr = (struct fcoe_ctlr_device *)ep;
Packit Service bca4e3
Packit Service bca4e3
	/* Iterate through the ctlr and add any fcfs */
Packit Service bca4e3
	sa_dir_read(ctlr->path, add_fcoe_fcf_device, ctlr);
Packit Service bca4e3
Packit Service bca4e3
	/* Populate each fabric */
Packit Service bca4e3
	sa_table_iterate(&ctlr->fcfs, read_fcoe_fcf_device, NULL);
Packit Service bca4e3
}
Packit Service bca4e3
Packit Service bca4e3
static void free_fcoe_fcf_device(void *ep, UNUSED void *arg)
Packit Service bca4e3
{
Packit Service bca4e3
	struct fcoe_fcf_device *fcf = (struct fcoe_fcf_device *)ep;
Packit Service bca4e3
Packit Service bca4e3
	free(fcf);
Packit Service bca4e3
}
Packit Service bca4e3
Packit Service bca4e3
#define SYSFS_MOUNT "/sys"
Packit Service bca4e3
#define FCOE_CTLR_DEVICE_DIR SYSFS_MOUNT "/bus/fcoe/devices/"
Packit Service bca4e3
Packit Service bca4e3
static int find_fchost(struct dirent *dp, void *arg)
Packit Service bca4e3
{
Packit Service bca4e3
	char *fchost = arg;
Packit Service bca4e3
Packit Service bca4e3
	if (strstr(dp->d_name, "host")) {
Packit Service bca4e3
		strncpy(fchost, dp->d_name, MAX_STR_LEN);
Packit Service bca4e3
		return 1;
Packit Service bca4e3
	}
Packit Service bca4e3
Packit Service bca4e3
	return 0;
Packit Service bca4e3
}
Packit Service bca4e3
Packit Service bca4e3
static int read_fcoe_ctlr_device(struct dirent *dp, void *arg)
Packit Service bca4e3
{
Packit Service bca4e3
	struct sa_table *ctlrs = arg;
Packit Service bca4e3
	struct fcoe_ctlr_device *ctlr;
Packit Service bca4e3
	char buf[MAX_STR_LEN];
Packit Service bca4e3
	char lesb_path[MAX_STR_LEN];
Packit Service bca4e3
	char hpath[MAX_STR_LEN];
Packit Service bca4e3
	char fchost[MAX_STR_LEN];
Packit Service bca4e3
	char *cp, *ifname;
Packit Service bca4e3
	int rc;
Packit Service bca4e3
Packit Service bca4e3
	if (strncmp(dp->d_name, "ctlr_", 5))
Packit Service bca4e3
		return 0;
Packit Service bca4e3
Packit Service bca4e3
	ctlr = malloc(sizeof(struct fcoe_ctlr_device));
Packit Service bca4e3
	if (!ctlr)
Packit Service bca4e3
		return 0; /* Must return 0 or loop will break */
Packit Service bca4e3
Packit Service bca4e3
	memset(ctlr, 0, sizeof(struct fcoe_ctlr_device));
Packit Service bca4e3
	sa_table_init(&ctlr->fcfs);
Packit Service bca4e3
Packit Service bca4e3
	/* Save the path */
Packit Service bca4e3
	snprintf(ctlr->path, sizeof(ctlr->path),
Packit Service bca4e3
		 FCOE_CTLR_DEVICE_DIR "%s", dp->d_name);
Packit Service bca4e3
Packit Service bca4e3
	/* Use the index from the logical enumeration */
Packit Service bca4e3
	ctlr->index = atoi(dp->d_name + sizeof("ctlr_") - 1);
Packit Service bca4e3
Packit Service bca4e3
	rc = sa_dir_read(ctlr->path, find_fchost, fchost);
Packit Service bca4e3
	if (!rc)
Packit Service bca4e3
		goto fail;
Packit Service bca4e3
Packit Service bca4e3
	rc = snprintf(hpath, MAX_STR_LEN, "%s/%s/", SYSFS_FCHOST, fchost);
Packit Service bca4e3
	if (rc < 0 || rc >= MAX_STR_LEN)
Packit Service bca4e3
		goto fail;
Packit Service bca4e3
Packit Service bca4e3
	rc = sa_sys_read_line(hpath, "symbolic_name", buf, sizeof(buf));
Packit Service bca4e3
Packit Service bca4e3
	/* Skip the HBA if it isn't Open-FCoE */
Packit Service bca4e3
	cp = strstr(buf, " over ");
Packit Service bca4e3
	if (!cp)
Packit Service bca4e3
		goto fail;
Packit Service bca4e3
Packit Service bca4e3
	ifname = get_ifname_from_symbolic_name(buf);
Packit Service bca4e3
	strncpy(ctlr->ifname, ifname, IFNAMSIZ-1);
Packit Service bca4e3
Packit Service bca4e3
	/* Get fcf device loss timeout */
Packit Service bca4e3
	sa_sys_read_u32(ctlr->path, "fcf_dev_loss_tmo",
Packit Service bca4e3
			&ctlr->fcf_dev_loss_tmo);
Packit Service bca4e3
Packit Service bca4e3
	sa_sys_read_line(ctlr->path, "mode", buf, sizeof(buf));
Packit Service bca4e3
	sa_enum_encode(fip_conn_type_table, buf, &ctlr->mode);
Packit Service bca4e3
Packit Service bca4e3
	if (safe_makepath(lesb_path, sizeof(lesb_path),
Packit Service bca4e3
				ctlr->path, "lesb") == NULL)
Packit Service bca4e3
		goto fail;
Packit Service bca4e3
Packit Service bca4e3
	/* Get LESB statistics */
Packit Service bca4e3
	sa_sys_read_u32(lesb_path, "link_fail",
Packit Service bca4e3
			&ctlr->lesb_link_fail);
Packit Service bca4e3
	sa_sys_read_u32(lesb_path, "vlink_fail",
Packit Service bca4e3
			&ctlr->lesb_vlink_fail);
Packit Service bca4e3
	sa_sys_read_u32(lesb_path, "miss_fka",
Packit Service bca4e3
			&ctlr->lesb_miss_fka);
Packit Service bca4e3
	sa_sys_read_u32(lesb_path, "symb_err",
Packit Service bca4e3
			&ctlr->lesb_symb_err);
Packit Service bca4e3
	sa_sys_read_u32(lesb_path, "err_block",
Packit Service bca4e3
			&ctlr->lesb_err_block);
Packit Service bca4e3
	sa_sys_read_u32(lesb_path, "fcs_error",
Packit Service bca4e3
			&ctlr->lesb_fcs_error);
Packit Service bca4e3
Packit Service bca4e3
	/* Save the ctlr in the supplied table */
Packit Service bca4e3
	if (sa_table_insert(ctlrs, ctlr->index, ctlr) < 0) {
Packit Service bca4e3
		fprintf(stderr, "%s: insert of ctlr %d failed\n",
Packit Service bca4e3
			__func__, ctlr->index);
Packit Service bca4e3
		goto fail;
Packit Service bca4e3
	}
Packit Service bca4e3
Packit Service bca4e3
	return 0;
Packit Service bca4e3
Packit Service bca4e3
fail:
Packit Service bca4e3
	free(ctlr);
Packit Service bca4e3
	return -ENOENT;
Packit Service bca4e3
}
Packit Service bca4e3
Packit Service bca4e3
void read_fcoe_ctlr(struct sa_table *ctlrs)
Packit Service bca4e3
{
Packit Service bca4e3
	sa_dir_read(FCOE_CTLR_DEVICE_DIR, read_fcoe_ctlr_device, ctlrs);
Packit Service bca4e3
	sa_table_iterate(ctlrs, read_fcoe_fcf, NULL);
Packit Service bca4e3
}
Packit Service bca4e3
Packit Service bca4e3
void free_fcoe_ctlr_device(void *ep, UNUSED void *arg)
Packit Service bca4e3
{
Packit Service bca4e3
	struct fcoe_ctlr_device *ctlr = (struct fcoe_ctlr_device *)ep;
Packit Service bca4e3
Packit Service bca4e3
	sa_table_iterate(&ctlr->fcfs, free_fcoe_fcf_device, NULL);
Packit Service bca4e3
Packit Service bca4e3
	free(ctlr);
Packit Service bca4e3
}