|
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 |
}
|