File fcoe-utils-beta2-update of Package open-fcoe
diff -Pur --exclude=.git fcoe-utils/configure.ac fcoe-utils-tip/configure.ac
--- fcoe-utils/configure.ac 2010-01-08 15:43:45.067000276 -0800
+++ fcoe-utils-tip/configure.ac 2010-01-08 12:15:27.545000527 -0800
@@ -1,4 +1,4 @@
-AC_INIT([fcoe-utils], [1.0.7], [devel@open-fcoe.org])
+AC_INIT([fcoe-utils], [1.0.9], [devel@open-fcoe.org])
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
AC_PROG_CC
@@ -19,6 +19,6 @@
[PKG_CHECK_MODULES([DCBD], [dcbd])
AC_SUBST([DCBD_CFLAGS])])
-AC_CONFIG_FILES([Makefile fcoeplumb fcoe-utils.spec])
+AC_CONFIG_FILES([Makefile fcoeplumb fcoe-utils.spec fcoe_utils.h])
AC_OUTPUT
diff -Pur --exclude=.git fcoe-utils/etc/initd/initd.fedora fcoe-utils-tip/etc/initd/initd.fedora
--- fcoe-utils/etc/initd/initd.fedora 2010-01-08 16:56:17.511000544 -0800
+++ fcoe-utils-tip/etc/initd/initd.fedora 2010-01-08 12:15:27.548000527 -0800
@@ -118,31 +118,14 @@
fi
}
-validate_link_flow_control()
-{
- ifname=$1
-
- retry_count=1
- while true
- do
- TX_STATUS=`ethtool -a $ifname 2>&1 | awk '/TX:/{print $2}'`
- RX_STATUS=`ethtool -a $ifname 2>&1 | awk '/RX:/{print $2}'`
-
- if [ "$TX_STATUS" = "on" ] && [ "$RX_STATUS" = "on" ]; then
- return 0
- fi
-
- ethtool -A $ifname rx on tx on
- [ $retry_count -eq 0 ] && return 0
- retry_count=$(($retry_count-1))
- usleep 500000
- done
- $LOGGER "Warning: Failed to bring up link flow control of $ifname."
- return 1
-}
-
service_start()
{
+ pidof $FCOEMON
+ if [ $? -eq 0 ]; then
+ $LOGGER "Warning: daemon already running."
+ return
+ fi
+
rm -f /var/run/fcoemon.*
modprobe -q libfc
@@ -158,22 +141,6 @@
pidof $FCOEMON
[ $? -eq 0 ] && kill -TERM `pidof $FCOEMON`
- for ifcfg_file in `ls $CONFIG_DIR/cfg-eth*`
- do
- ifname=`basename $ifcfg_file | cut -d"-" -f2`
- . $ifcfg_file
- [ "$FCOE_ENABLE" != "yes" ] &&
- [ "$FCOE_ENABLE" != "YES" ] && continue
- if [ "$DCB_REQUIRED" != "yes" ] &&
- [ "$DCB_REQUIRED" != "YES" ]; then
- STATUS=`$FCOEADM -i $ifname 2>&1 | \
- awk '/Symbolic Name:/{print $6}'`
- if [ "$STATUS" = "$ifname" ]; then
- $FCOEADM -d $ifname
- fi
- fi
- done
-
retry_count=5
while true
do
diff -Pur --exclude=.git fcoe-utils/etc/initd/initd.suse fcoe-utils-tip/etc/initd/initd.suse
--- fcoe-utils/etc/initd/initd.suse 2010-01-08 15:43:45.069000342 -0800
+++ fcoe-utils-tip/etc/initd/initd.suse 2010-01-08 12:15:27.548000527 -0800
@@ -189,42 +189,7 @@
startup_fcoe_modules
- HAS_DCB_IF="false"
- for ifcfg_file in `ls $CONFIG_DIR/cfg-eth*`
- do
- ifname=`basename $ifcfg_file | cut -d"-" -f2`
- . $ifcfg_file
- [ "$FCOE_ENABLE" != "yes" ] &&
- [ "$FCOE_ENABLE" != "YES" ] && continue
-
- if [ "$DCB_REQUIRED" != "yes" ] &&
- [ "$DCB_REQUIRED" != "YES" ]; then
- #
- # DCB is not required, we nee to validate the
- # link flow control of the Ethernet port
- #
- validate_link_flow_control $ifname
- [ $? -ne 0 ] && continue
- #
- # Create the FCoE interface
- #
- $FCOEADM -c $ifname
- else
- #
- # Configure the DCB for the Ethernet
- # port if DCB is required
- #
- HAS_DCB_IF="true"
- fi
- done
-
- #
- # If DCB-required Ethernet port exists, then start the fcoemon
- # daemon to create the FCoE interfaces for these ports.
- #
- if [ "$HAS_DCB_IF" = "true" ]; then
- startproc -l ${LOG_FILE} -p ${PID_FILE} ${FCOEMON} ${FCOEMON_OPTS}
- fi
+ startproc -l ${LOG_FILE} -p ${PID_FILE} ${FCOEMON} ${FCOEMON_OPTS}
rc_status -v
return
@@ -235,22 +200,6 @@
checkproc $FCOEMON
[ $? -eq 0 ] && killproc -TERM $FCOEMON
- for ifcfg_file in `ls $CONFIG_DIR/cfg-eth*`
- do
- ifname=`basename $ifcfg_file | cut -d"-" -f2`
- . $ifcfg_file
- [ "$FCOE_ENABLE" != "yes" ] &&
- [ "$FCOE_ENABLE" != "YES" ] && continue
- if [ "$DCB_REQUIRED" != "yes" ] &&
- [ "$DCB_REQUIRED" != "YES" ]; then
- STATUS=`$FCOEADM -i $ifname 2>&1 | \
- awk '/Symbolic Name:/{print $6}'`
- if [ "$STATUS" = "$ifname" ]; then
- $FCOEADM -d $ifname
- fi
- fi
- done
-
retry_count=5
while true
do
diff -Pur --exclude=.git fcoe-utils/fcoeadm.c fcoe-utils-tip/fcoeadm.c
--- fcoe-utils/fcoeadm.c 2010-01-08 16:56:55.791000544 -0800
+++ fcoe-utils-tip/fcoeadm.c 2010-01-08 12:15:27.550000527 -0800
@@ -17,17 +17,17 @@
* Maintained at www.Open-FCoE.org
*/
-#include <stdio.h>
-#include <stdlib.h>
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
#include <libgen.h>
-#include <errno.h>
-#include <getopt.h>
-#include <dirent.h>
+#include <paths.h>
+#include "fcoe_utils.h"
#include "fcoeadm.h"
#include "fcoe_clif.h"
-static char *fcoeadm_version = \
- "fcoeadm v1.0.9\n Copyright (c) 2009, Intel Corporation.\n";
+static char *fcoeadm_version =
+"fcoeadm v" FCOE_UTILS_VERSION "\n Copyright (c) 2009, Intel Corporation.\n";
#define CMD_RESPONSE_TIMEOUT 5
@@ -49,12 +49,6 @@
struct clif *clif_conn;
-enum { /* Match the values in fcoemon */
- FCOEADM_CREATE = 1,
- FCOEADM_DESTROY,
- FCOEADM_RESET,
-};
-
static void fcoeadm_help(void)
{
printf("%s\n", fcoeadm_version);
@@ -71,81 +65,42 @@
}
/*
- * Open and close to check if directory exists
- */
-static int fcoeadm_checkdir(char *dir)
-{
- DIR *d = NULL;
-
- if (!dir)
- return -EINVAL;
- /* check if we have sysfs */
- d = opendir(dir);
- if (!d)
- return -EINVAL;
- closedir(d);
- return 0;
-}
-
-/*
* TODO - check this ifname before performing any action
*/
static int fcoeadm_check(char *ifname)
{
char path[256];
+ int fd;
+ int status = 0;
/* check if we have sysfs */
- if (fcoeadm_checkdir(SYSFS_MOUNT)) {
+ if (fcoeclif_checkdir(SYSFS_MOUNT)) {
fprintf(stderr,
"%s: Sysfs mount point %s not found!\n",
progname, SYSFS_MOUNT);
- return -EINVAL;
- }
- /* check fcoe module */
- if (fcoeadm_checkdir(SYSFS_FCOE)) {
- fprintf(stderr,
- "%s: Please make sure FCoE driver module is loaded!\n",
- progname);
- return -EINVAL;
+ status = -EINVAL;
}
+
/* check target interface */
if (!ifname) {
fprintf(stderr, "%s: Invalid interface name!\n", progname);
- return -EINVAL;
+ status = -EINVAL;
}
sprintf(path, "%s/%s", SYSFS_NET, ifname);
- if (fcoeadm_checkdir(path)) {
+ if (fcoeclif_checkdir(path)) {
fprintf(stderr,
"%s: Interface %s not found!\n", progname, ifname);
- return -EINVAL;
+ status = -EINVAL;
}
- return 0;
-}
-
-static int fcoeadm_print_response(char *rbuf, int rlen,
- char *device_name, int cmd)
-{
- fprintf(stdout, "Command :\t");
- switch (cmd) {
- case FCOEADM_CREATE:
- fprintf(stdout, "FCOEADM CREATE\n");
- break;
- case FCOEADM_RESET:
- fprintf(stdout, "FCOEADM RESET\n");
- break;
- case FCOEADM_DESTROY:
- fprintf(stdout, "FCOEADM DELETE\n");
- break;
- default:
- fprintf(stderr, "BAD COMMAND\n");
+ fd = open(CLIF_PID_FILE, O_RDWR, S_IRUSR | S_IWUSR);
+ if (fd < 0) {
+ fprintf(stderr,
+ "%s: fcoemon was not running!\n", progname);
+ status = -EINVAL;
}
- fprintf(stdout, "Port Name:\t%s\n", device_name);
-
- fprintf(stdout, "Status :\t%s\n", atoi(rbuf) ? "FAIL" : "SUCCESS");
-
- return 0;
+ return status;
}
static int fcoeadm_clif_request(const struct clif_data *cmd, size_t cmd_len,
@@ -213,7 +168,7 @@
}
rbuf[len] = '\0';
- ret = fcoeadm_print_response(rbuf, len, s, cmd);
+ ret = atoi(rbuf);
free(data);
return ret;
@@ -242,9 +197,6 @@
int flen;
static int counter;
- if (ifname == NULL)
- return NULL;
-
flen = strlen(FCM_SRV_DIR) + strlen(ifname) + 2;
fcmon_file = malloc(flen);
if (fcmon_file == NULL)
@@ -317,7 +269,6 @@
clif_conn = fcoeadm_open_cli(clif_ifname);
if (clif_conn) {
- fprintf(stdout, "Connection established.\n");
break;
} else {
fprintf(stderr, "Failed to connect to fcoemon.\n");
@@ -345,7 +296,7 @@
progname, ifname);
return -EINVAL;
}
- return fcoeadm_action(FCOEADM_CREATE, ifname);
+ return fcoeadm_action(FCOE_CREATE_CMD, ifname);
}
/*
@@ -359,7 +310,7 @@
progname, ifname);
return -EINVAL;
}
- return fcoeadm_action(FCOEADM_DESTROY, ifname);
+ return fcoeadm_action(FCOE_DESTROY_CMD, ifname);
}
/*
@@ -367,7 +318,7 @@
*/
static int fcoeadm_reset(char *ifname)
{
- return fcoeadm_action(FCOEADM_RESET, ifname);
+ return fcoeadm_action(FCOE_RESET_CMD, ifname);
}
/*
@@ -540,7 +491,7 @@
sizeof(opt_info->ifname));
}
if (strnlen(opt_info->ifname, IFNAMSIZ - 1)) {
- if (fcoeadm_validate_interface(
+ if (fcoeclif_validate_interface(
opt_info->ifname,
fchost, FCHOSTBUFLEN))
goto done;
@@ -570,7 +521,7 @@
sizeof(opt_info->ifname));
}
if (strnlen(opt_info->ifname, IFNAMSIZ - 1)) {
- if (fcoeadm_validate_interface(
+ if (fcoeclif_validate_interface(
opt_info->ifname,
fchost, FCHOSTBUFLEN))
goto done;
@@ -601,7 +552,7 @@
strncpy(opt_info->ifname, optarg,
sizeof(opt_info->ifname));
if (strnlen(opt_info->ifname, IFNAMSIZ - 1)) {
- if (fcoeadm_validate_interface(
+ if (fcoeclif_validate_interface(
opt_info->ifname,
fchost, FCHOSTBUFLEN))
goto done;
diff -Pur --exclude=.git fcoe-utils/fcoeadm.h fcoe-utils-tip/fcoeadm.h
--- fcoe-utils/fcoeadm.h 2010-01-08 16:56:55.792000544 -0800
+++ fcoe-utils-tip/fcoeadm.h 2010-01-08 12:15:27.550000527 -0800
@@ -49,9 +49,6 @@
#include "fc_types.h"
#include "fc_scsi.h"
-#define __USE_GNU
-#include <string.h>
-
#define FCOE_MAX_LUN 255
struct opt_info {
@@ -72,8 +69,7 @@
/**
* struct clif - Internal structure for client interface library
*
- * This structure is used by the fcmon and fcoeadm client interface
- * libraryto store internal data.
+ * This structure is used by fcoeadm client interface to store internal data.
*/
struct clif {
int s;
diff -Pur --exclude=.git fcoe-utils/fcoe_clif.c fcoe-utils-tip/fcoe_clif.c
--- fcoe-utils/fcoe_clif.c 2010-01-08 16:56:55.790000544 -0800
+++ fcoe-utils-tip/fcoe_clif.c 2010-01-08 12:15:27.549000527 -0800
@@ -17,6 +17,9 @@
* Maintained at www.Open-FCoE.org
*/
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -26,15 +29,12 @@
#include <errno.h>
#include "fcoe_clif.h"
-static char *fcoeadm_read(const char *path)
+static char *fcoeclif_read(const char *path)
{
FILE *fp;
char *buf;
int size = 512;
- if (!path)
- return NULL;
-
buf = malloc(size);
if (!buf)
return NULL;
@@ -52,22 +52,16 @@
return NULL;
}
-static int fcoeadm_check_fchost(const char *ifname, const char *dname)
+static int fcoeclif_check_fchost(const char *ifname, const char *dname)
{
char *buf;
char path[512];
- if (!ifname)
- return -EINVAL;
-
- if (!dname)
- return -EINVAL;
-
if (dname[0] == '.')
return -EINVAL;
sprintf(path, "%s/%s/symbolic_name", SYSFS_FCHOST, dname);
- buf = fcoeadm_read(path);
+ buf = fcoeclif_read(path);
if (!buf)
return -EINVAL;
@@ -79,24 +73,18 @@
return 0;
}
-static int fcoeadm_find_fchost(char *ifname, char *fchost, int len)
+static int fcoeclif_find_fchost(char *ifname, char *fchost, int len)
{
int n, dname_len;
int found = 0;
struct dirent **namelist;
- if (!ifname)
- return -EINVAL;
-
- if ((!fchost) || (len <= 0))
- return -EINVAL;
-
memset(fchost, 0, len);
n = scandir(SYSFS_FCHOST, &namelist, 0, alphasort);
if (n > 0) {
while (n--) {
/* check symbolic name */
- if (!fcoeadm_check_fchost(ifname,
+ if (!fcoeclif_check_fchost(ifname,
namelist[n]->d_name)) {
dname_len = strnlen(namelist[n]->d_name, len);
if (dname_len != len) {
@@ -126,12 +114,33 @@
/*
* Validate an existing instance for an FC interface
*/
-int fcoeadm_validate_interface(char *ifname, char *fchost, int len)
+int fcoeclif_validate_interface(char *ifname, char *fchost, int len)
{
- if (!fcoeadm_find_fchost(ifname, fchost, len)) {
+ if ((!ifname) || (!fchost) || (len <= 0))
+ return -EINVAL;
+
+ if (!fcoeclif_find_fchost(ifname, fchost, len)) {
fprintf(stderr, "No fc_host found for %s\n", ifname);
return -EINVAL;
}
return 0;
}
+
+
+/*
+ * Open and close to check if directory exists
+ */
+int fcoeclif_checkdir(char *dir)
+{
+ DIR *d = NULL;
+
+ if (!dir)
+ return -EINVAL;
+ /* check if we have sysfs */
+ d = opendir(dir);
+ if (!d)
+ return -EINVAL;
+ closedir(d);
+ return 0;
+}
diff -Pur --exclude=.git fcoe-utils/fcoe_clif.h fcoe-utils-tip/fcoe_clif.h
--- fcoe-utils/fcoe_clif.h 2010-01-08 16:56:55.790000544 -0800
+++ fcoe-utils-tip/fcoe_clif.h 2010-01-08 12:15:27.549000527 -0800
@@ -20,16 +20,15 @@
#ifndef _FCOE_CLIF_H_
#define _FCOE_CLIF_H_
-#define FCM_SRV_DIR "/var/run/fcm"
-#define CLIF_IFNAME "fcm_clif"
-#define MAX_MSGBUF 512
-#define FCHOSTBUFLEN 64
#define SYSFS_MOUNT "/sys"
#define SYSFS_NET SYSFS_MOUNT "/class/net"
#define SYSFS_FCHOST SYSFS_MOUNT "/class/fc_host"
#define SYSFS_FCOE SYSFS_MOUNT "/module/fcoe/parameters"
-#define FCOE_CREATE SYSFS_FCOE "/create"
-#define FCOE_DESTROY SYSFS_FCOE "/destroy"
+#define FCM_SRV_DIR "/var/run/fcm"
+#define CLIF_IFNAME "fcm_clif"
+#define FCHOSTBUFLEN 64
+#define MAX_MSGBUF 512
+#define CLIF_PID_FILE _PATH_VARRUN "fcoemon.pid"
enum clif_status {
CLI_SUCCESS = 0,
@@ -37,6 +36,12 @@
CLI_NO_ACTION
};
+enum {
+ FCOE_CREATE_CMD = 1,
+ FCOE_DESTROY_CMD,
+ FCOE_RESET_CMD,
+};
+
/*
* Description of fcoemon and fcoeadm socket data structure interface
*/
@@ -45,5 +50,6 @@
char ifname[IFNAMSIZ];
};
-int fcoeadm_validate_interface(char *ifname, char *fchost, int len);
+int fcoeclif_validate_interface(char *ifname, char *fchost, int len);
+int fcoeclif_checkdir(char *dir);
#endif /* _FCOE_CLIF_H_ */
diff -Pur --exclude=.git fcoe-utils/fcoemon.c fcoe-utils-tip/fcoemon.c
--- fcoe-utils/fcoemon.c 2010-01-08 16:56:55.793000544 -0800
+++ fcoe-utils-tip/fcoemon.c 2010-01-08 12:15:27.551000527 -0800
@@ -56,6 +56,7 @@
#include "net_types.h"
#include "fc_types.h"
+#include "fcoe_utils.h"
#include "fcoemon_utils.h"
#include "fcoemon.h"
#include "fcoe_clif.h"
@@ -75,7 +76,6 @@
#define VLAN_DIR "/proc/net/vlan"
#define CLIF_NAME_PATH _PATH_VARRUN "dcbd/clif"
-#define CLIF_PID_FILE _PATH_VARRUN "fcoemon.pid"
#define CLIF_LOCAL_SUN_PATH _PATH_TMP "fcoemon.dcbd.%d"
#define DCBD_CONNECT_TIMEOUT (10 * 1000 * 1000) /* 10 seconds */
#define DCBD_CONNECT_RETRY_TIMEOUT (1 * 1000 * 1000) /* 1 seconds */
@@ -84,8 +84,11 @@
#define FCM_PING_REQ_LEN 1 /* byte-length of dcbd PING request */
#define FCM_PING_RSP_LEN 8 /* byte-length of dcbd PING response */
-static char *fcoemon_version = \
- "fcoemon v1.0.8\n Copyright (c) 2009, Intel Corporation.\n";
+#define FCOE_CREATE SYSFS_FCOE "/create"
+#define FCOE_DESTROY SYSFS_FCOE "/destroy"
+
+static char *fcoemon_version =
+"fcoemon v" FCOE_UTILS_VERSION "\n Copyright (c) 2009, Intel Corporation.\n";
enum fcm_srv_status {
fcm_success = 0,
@@ -95,7 +98,6 @@
static struct fcm_srv_data *srv_data;
-
/*
* fcoe service configuration data
* Note: These information are read in from the fcoe service
@@ -153,7 +155,7 @@
char *fcm_dcbd_cmd = CONFIG_DIR "/scripts/fcoeplumb";
/* Debugging routine */
-static void print_errors(char *buf, int errors);
+static void print_errors(int errors);
struct fcm_netif_head fcm_netif_head = TAILQ_HEAD_INITIALIZER(fcm_netif_head);
@@ -323,6 +325,7 @@
rc = fcm_read_config_variable(file, val, sizeof(val),
fp, "FCOE_ENABLE");
if (rc < 0) {
+ FCM_LOG("%s invalid format for FCOE_ENABLE setting");
fclose(fp);
free(next);
continue;
@@ -335,6 +338,7 @@
rc = fcm_read_config_variable(file, val, sizeof(val),
fp, "DCB_REQUIRED");
if (rc < 0) {
+ FCM_LOG("%s invalid format for DCB_REQUIRED setting");
fclose(fp);
free(next);
continue;
@@ -366,7 +370,7 @@
* NULL - if not found
*/
static struct fcoe_port *fcm_find_next_fcoe_port(struct fcoe_port *p,
- char *ifname)
+ char *ifname)
{
struct fcoe_port *np;
@@ -390,17 +394,25 @@
}
static struct fcoe_port *fcm_find_fcoe_port(char *ifname,
- enum fcoeport_ifname t)
+ enum fcoeport_ifname t)
{
struct fcoe_port *p;
char *fp_ifname;
p = fcoe_config.port;
while (p) {
- if (t == FCP_CFG_IFNAME)
+ switch (t) {
+ case FCP_CFG_IFNAME:
fp_ifname = p->ifname;
- else
+ break;
+ case FCP_REAL_IFNAME:
fp_ifname = p->real_ifname;
+ break;
+ default:
+ FCM_LOG("unhandled interface type [%d] for %s",
+ t, ifname);
+ return NULL;
+ }
if (!strncmp(ifname, fp_ifname, IFNAMSIZ))
return p;
@@ -552,17 +564,66 @@
ff->response_pending = 0;
}
+static void update_fcoe_port_state(struct fcoe_port *p, unsigned int type,
+ u_int8_t operstate, enum fcoeport_ifname t)
+{
+ struct fcm_netif *ff = NULL;
+
+ if (type != RTM_DELLINK) {
+ ff = fcm_netif_lookup_create(p->real_ifname);
+ if (!ff)
+ return;
+
+ /* Only set the ff_operstate field of the network interface
+ * element if this routine is being called for the real
+ * network interface, or, if the interface is a VLAN, if the
+ * network interface element has not been intialized and the
+ * VLAN operstate is up (if VLAN is up, then real interface is
+ * up).
+ */
+ if ((t == FCP_REAL_IFNAME) ||
+ ((t == FCP_CFG_IFNAME) &&
+ (ff->ff_operstate == IF_OPER_UNKNOWN) &&
+ (operstate == IF_OPER_UP)))
+ ff->ff_operstate = operstate;
+
+ if (!p->fcoe_enable) {
+ p->action = FCP_DESTROY_IF;
+ return;
+ }
+
+ if (operstate == IF_OPER_UP) {
+ if (p->dcb_required) {
+ /* If DCB is required, do not start the dcbd
+ * query sequence if this routine is being
+ * called for a real interface and the FCoE
+ * interface is configured on a VLAN.
+ */
+ if ((t == FCP_REAL_IFNAME) &&
+ strncmp(p->ifname, p->real_ifname,
+ IFNAMSIZ))
+ fcm_dcbd_state_set(ff, FCD_INIT);
+ else
+ fcm_dcbd_state_set(ff,
+ FCD_GET_DCB_STATE);
+ } else {
+ p->action = FCP_CREATE_IF;
+ }
+ }
+ } else {
+ p->action = FCP_DESTROY_IF;
+ }
+}
+
void fcm_process_link_msg(struct ifinfomsg *ip, int len, unsigned type)
{
struct fcoe_port *p;
- struct fcm_netif *ff = NULL;
struct rtattr *ap;
char ifname[IFNAMSIZ];
char real_dev[IFNAMSIZ];
u_int8_t operstate;
u_int64_t mac;
int is_vlan;
- int dcb_required_cnt;
mac = is_vlan = 0;
operstate = IF_OPER_UNKNOWN;
@@ -608,101 +669,28 @@
/* try to find the real device name */
real_dev[0] = '\0';
- if (type != RTM_DELLINK) {
- fcm_vlan_dev_real_dev(ifname, real_dev);
- if (strlen(real_dev)) {
- strncpy(p->real_ifname, real_dev,
- strlen(real_dev)+1);
- ff = fcm_netif_lookup_create(real_dev);
- if (!ff)
- return;
- }
-
- if (operstate == IF_OPER_UP) {
- /* if ff was just created, initialize
- * operstate to the value of the VLAN
- * interface. Since the VLAN interface
- * is up, the underlying real interface
- * should be up too.
- */
- if (ff->ff_operstate == IF_OPER_UNKNOWN)
- ff->ff_operstate = operstate;
-
- if (p->fcoe_enable) {
- if (p->dcb_required)
- fcm_dcbd_state_set(ff,
- FCD_GET_DCB_STATE);
- else
- p->action = FCP_CREATE_IF;
- }
- }
- if (!p->fcoe_enable)
- p->action = FCP_DESTROY_IF;
- } else {
- p->action = FCP_DESTROY_IF;
- }
+ fcm_vlan_dev_real_dev(ifname, real_dev);
+ if (strlen(real_dev))
+ strncpy(p->real_ifname, real_dev, strlen(real_dev)+1);
+ update_fcoe_port_state(p, type, operstate, FCP_CFG_IFNAME);
p->last_msg_type = type;
} else {
- /* there is an fcoe port configured to use this real netif.
- * make sure structures are up to date.
- */
- if (p && type != RTM_DELLINK) {
+ /* the ifname is not a VLAN. handle the case where it has
+ * an FCoE interface configured on it.
+ */
+ if (p) {
strncpy(p->real_ifname, ifname, strlen(ifname)+1);
- ff = fcm_netif_lookup_create(ifname);
- if (!ff)
- return;
- ff->ff_operstate = operstate;
- if (p->fcoe_enable) {
- if (!p->dcb_required && operstate == IF_OPER_UP)
- p->action = FCP_CREATE_IF;
- if (p->dcb_required && operstate != IF_OPER_UP)
- fcm_dcbd_state_set(ff, FCD_INIT);
- } else {
- p->action = FCP_DESTROY_IF;
- }
- } else if (p && type == RTM_DELLINK) {
- p->action = FCP_DESTROY_IF;
- } else if (p && !p->fcoe_enable) {
- p->action = FCP_DESTROY_IF;
+ update_fcoe_port_state(p, type, operstate,
+ FCP_REAL_IFNAME);
}
- if (!ff)
- ff = fcm_netif_lookup(ifname);
- if (ff)
- ff->ff_operstate = operstate;
-
- /* scan for all fcoe port's which use this netif as a
- * real netif.
- */
+ /* handle all FCoE ports which are on VLANs over this
+ * ifname.
+ */
p = fcm_find_fcoe_port(ifname, FCP_REAL_IFNAME);
- dcb_required_cnt = 0;
while (p) {
- ff = fcm_netif_lookup_create(ifname);
- if (!ff)
- break;
- ff->ff_operstate = operstate;
-
- if (p->fcoe_enable && p->last_msg_type != RTM_DELLINK) {
- if (operstate == IF_OPER_UP) {
- if (p->dcb_required) {
- fcm_dcbd_state_set(ff,
- FCD_GET_DCB_STATE);
- dcb_required_cnt++;
- } else if (!dcb_required_cnt) {
- fcm_dcbd_state_set(ff,
- FCD_INIT);
- }
- } else {
- if (p->dcb_required)
- fcm_dcbd_state_set(ff,
- FCD_INIT);
- if (type == RTM_DELLINK)
- p->action = FCP_DESTROY_IF;
- }
- } else {
- p->action = FCP_DESTROY_IF;
- }
-
+ update_fcoe_port_state(p, type, operstate,
+ FCP_REAL_IFNAME);
p = fcm_find_next_fcoe_port(p, ifname);
}
}
@@ -819,7 +807,6 @@
return 0;
}
-
static void fcm_fcoe_init(void)
{
if (fcm_read_config_files())
@@ -1138,7 +1125,7 @@
* past the interface name.
*/
static struct fcm_netif *fcm_dcbd_get_port(char **msgp, size_t len_off,
- size_t len_len, size_t len)
+ size_t len_len, size_t len)
{
struct fcm_netif *ff;
u_int32_t if_len;
@@ -1261,7 +1248,7 @@
* FCP_DESTROY_IF - if the dcb netif should not support fcoe interface
* FCP_WAIT - if dcb criteria is inconclusive
*/
-static int validate_dcbd_info(struct fcm_netif *ff)
+static enum fcp_action validate_dcbd_info(struct fcm_netif *ff)
{
int errors = 0;
int dcbon;
@@ -1334,7 +1321,7 @@
/* The dcbd state does not match the create or destroy criteria.
* Log possible problems.
- */
+ */
if (dcbon && !ff->ff_app_info.willing) {
FCM_LOG_DEV(ff, "WARNING: FCoE willing mode is false\n");
errors++;
@@ -1345,7 +1332,7 @@
}
if (dcbon && !ff->ff_app_info.op_mode) {
FCM_LOG_DEV(ff, "WARNING: FCoE operational mode is false\n");
- print_errors("", ff->ff_app_info.op_error);
+ print_errors(ff->ff_app_info.op_error);
errors++;
}
if (dcbon && !ff->ff_pfc_info.enable) {
@@ -1356,9 +1343,14 @@
FCM_LOG_DEV(ff, "WARNING: PFC advertise mode is false\n");
errors++;
}
+ if (dcbon && !ff->ff_app_info.op_mode) {
+ FCM_LOG_DEV(ff, "WARNING: APP:0 operational mode is false\n");
+ print_errors(ff->ff_app_info.op_error);
+ errors++;
+ }
if (dcbon && !ff->ff_pfc_info.op_mode) {
FCM_LOG_DEV(ff, "WARNING: PFC operational mode is false\n");
- print_errors("", ff->ff_pfc_info.op_error);
+ print_errors(ff->ff_pfc_info.op_error);
errors++;
}
if (dcbon && !(ff->ff_pfc_info.u.pfcup & ff->ff_app_info.u.appcfg)) {
@@ -1459,7 +1451,7 @@
fcm_dcbd_state_set(ff, FCD_ERROR);
} else {
if (val && fcoe_config.debug)
- print_errors("", val);
+ print_errors(val);
switch (ff->ff_dcbd_state) {
case FCD_GET_PFC_OPER:
@@ -1492,18 +1484,6 @@
}
}
-/**
- * fcm_dcbd_get_peer() - Response handler for get peer command
- * @ff: fcoe port structure
- * @resp: response buffer
- * @cp: response buffer pointer, points past the interface name
- * @st: status
- */
-static void fcm_dcbd_get_peer(struct fcm_netif *ff, char *resp, char *cp)
-{
- return;
-}
-
/*
* Handle command response.
* Response buffer points past command code character in response.
@@ -1554,7 +1534,7 @@
/*
* check that dcbd response matches the current dcbd state.
- */
+ */
state = ff->ff_dcbd_state;
if (((cmd == CMD_GET_CONFIG) &&
((state == FCD_GET_DCB_STATE && feature == FEATURE_DCB) ||
@@ -1586,10 +1566,6 @@
fcm_dcbd_get_oper(ff, resp, cp);
break;
- case CMD_GET_PEER:
- fcm_dcbd_get_peer(ff, resp, cp);
- break;
-
default:
FCM_LOG_DEV_DBG(ff, "Unknown cmd 0x%x in response: resp %s",
cmd, resp);
@@ -1631,7 +1607,7 @@
/*
* Check if the FCoE ports which use the interface on which the
* dcbd event arrived are configured to require dcb.
- */
+ */
p = fcm_find_fcoe_port(ff->ifname, FCP_REAL_IFNAME);
while (p) {
@@ -1754,7 +1730,7 @@
break;
case FCP_RESET_IF:
FCM_LOG_DBG("OP: RESET\n");
- if (fcoeadm_validate_interface(ifname, fchost, FCHOSTBUFLEN)) {
+ if (fcoeclif_validate_interface(ifname, fchost, FCHOSTBUFLEN)) {
fcm_cli_reply(p->sock_reply, CLI_FAIL);
return;
}
@@ -1827,9 +1803,8 @@
if (rc < 0)
FCM_LOG_ERR(errno, "fork error");
else if (rc == 0) { /* child process */
- execlp(fcm_dcbd_cmd, fcm_dcbd_cmd, p->ifname,
- p->real_ifname, qos_arg, qos, debug, syslog,
- (char *)NULL);
+ execlp(fcm_dcbd_cmd, fcm_dcbd_cmd, p->real_ifname,
+ qos_arg, qos, debug, syslog, (char *)NULL);
}
exit(1);
@@ -1972,13 +1947,13 @@
/*
* Perform pending actions (dcbd queries) on network interfaces.
- */
+ */
TAILQ_FOREACH(ff, &fcm_netif_head, ff_list)
fcm_netif_advance(ff);
/*
* Perform actions on FCoE ports
- */
+ */
i = 0;
p = fcoe_config.port;
while (p) {
@@ -2006,6 +1981,7 @@
{
printf("%s\n", fcoemon_version);
printf("Usage: %s\n"
+ "\t [-e|--exec <exec>]\n"
"\t [-f|--foreground]\n"
"\t [-d|--debug]\n"
"\t [-s|--syslog]\n"
@@ -2384,6 +2360,9 @@
fcoe_config.use_syslog = 1;
enable_syslog(1);
break;
+ case 'e':
+ fcm_dcbd_cmd = optarg;
+ break;
case 'v':
printf("%s\n", fcoemon_version);
return 0;
@@ -2439,6 +2418,13 @@
exit(1);
}
fcm_pidfile_create();
+
+ /* check fcoe module */
+ if (fcoeclif_checkdir(SYSFS_FCOE)) {
+ FCM_LOG_ERR(errno, "make sure FCoE driver module is loaded!");
+ exit(1);
+ }
+
fcm_fcoe_init();
fcm_link_init(); /* NETLINK_ROUTE protocol */
fcm_dcbd_init();
@@ -2459,73 +2445,48 @@
/*******************************************************
* The following are debug routines *
*******************************************************/
+static void add_msg_to_buf(char *buf, int maxlen, char *msg, char *prefix)
+{
+ int len = strlen(buf);
-static void print_errors(char *buf, int errors)
+ if (len + strlen(msg) + strlen(prefix) < maxlen)
+ sprintf(buf+len, "%s%s", prefix, msg);
+}
+
+static void print_errors(int errors)
{
- char msg[80];
- int len, j;
- int flag = 0;
+ char msg[256];
+ int cnt = 0;
memset(msg, 0, sizeof(msg));
- len = sprintf(msg, "0x%02x - ", errors);
+ sprintf(msg, "0x%02x - ", errors);
- if (!errors) {
- j = sprintf(msg + len, "none\n");
- FCM_LOG("%s %s", buf, msg);
- return;
- }
+ if (errors & 0x01)
+ add_msg_to_buf(msg, sizeof(msg), "mismatch with peer",
+ (cnt++) ? ", " : "");
- if (errors & 0x01) {
- flag++;
- j = sprintf(msg + len, "mismatch with peer");
- len += j;
- }
+ if (errors & 0x02)
+ add_msg_to_buf(msg, sizeof(msg), "local configuration error",
+ (cnt++) ? ", " : "");
- if (errors & 0x02) {
- if (flag++) {
- j = sprintf(msg + len, ", ");
- len += j;
- }
- j = sprintf(msg + len, "local configuration error");
- len += j;
- }
+ if (errors & 0x04)
+ add_msg_to_buf(msg, sizeof(msg), "multiple TLV's received",
+ (cnt++) ? ", " : "");
- if (errors & 0x04) {
- if (flag++) {
- j = sprintf(msg + len, ", ");
- len += j;
- }
- j = sprintf(msg + len, "multiple TLV's received");
- len += j;
- }
+ if (errors & 0x08)
+ add_msg_to_buf(msg, sizeof(msg), "peer error",
+ (cnt++) ? ", " : "");
- if (errors & 0x08) {
- if (flag++) {
- j = sprintf(msg + len, ", ");
- len += j;
- }
- j = sprintf(msg + len, "peer error");
- len += j;
- }
+ if (errors & 0x10)
+ add_msg_to_buf(msg, sizeof(msg), "multiple LLDP neighbors",
+ (cnt++) ? ", " : "");
- if (errors & 0x10) {
- if (flag++) {
- j = sprintf(msg + len, ", ");
- len += j;
- }
- j = sprintf(msg + len, "multiple LLDP neighbors");
- len += j;
- }
+ if (errors & 0x20)
+ add_msg_to_buf(msg, sizeof(msg), "peer feature not present",
+ (cnt++) ? ", " : "");
- if (errors & 0x20) {
- j = len;
- if (flag++) {
- j = sprintf(msg + len, ", ");
- len += j;
- }
- j = sprintf(msg + len, "peer feature not present");
- len += j;
- }
+ if (!errors)
+ add_msg_to_buf(msg, sizeof(msg), "none", "");
- FCM_LOG("%s %s\n", buf, msg);
+ FCM_LOG("%s\n", msg);
}
diff -Pur --exclude=.git fcoe-utils/fcoeplumb.in fcoe-utils-tip/fcoeplumb.in
--- fcoe-utils/fcoeplumb.in 2010-01-08 16:56:55.795000544 -0800
+++ fcoe-utils-tip/fcoeplumb.in 2010-01-08 12:15:27.553000527 -0800
@@ -22,8 +22,8 @@
usage()
{
echo usage: $cmdname \
- '<ifname real_ifname> [--reset | --create | --destroy] [--debug] [--syslog]' \
- '[--qos-disable | --qos-enable <pri>[,<pri>]...]' >&2
+ '[--debug] [--syslog]' \
+ '[<ethX> --qos-disable | --qos-enable <pri>[,<pri>]...]' >&2
exit 1
}
@@ -207,22 +207,20 @@
[ ${DEBUG_LOGGING} ] && $LOGGER "fcoeplumb arguments: ($*)"
-ifname=$1
-shift
-real_ifname=$1
+net_ifname=$1
shift
while [ "$#" -ge 1 ]
do
case "$1" in
- --reset | -r)
- cmd=reset
- ;;
- --create | -c)
- cmd=create
+ --qos-enable)
+ [ "$#" -lt 2 ] && usage
+ qos_list=$2
+ shift
;;
- --destroy | -d)
- cmd=destroy
+ --qos-disable)
+ [[ "$2" =~ ^[0-9]+$ ]] && shift
+ qos_list="disable"
;;
--debug)
DEBUG_LOGGING=1
@@ -232,15 +230,6 @@
USE_SYSLOG=1
config_logging
;;
- --qos-enable)
- [ "$#" -lt 2 ] && usage
- qos_list=$2
- shift
- ;;
- --qos-disable)
- [[ "$2" =~ ^[0-9]+$ ]] && shift
- qos_list="disable"
- ;;
*)
echo "$cmdname: unknown parameter '$1'" >&2
usage
@@ -252,19 +241,21 @@
# This must be the first to do after parsing the command arguments!
# Notice that the filter ID is used in find_skbedit_filter(),
# add_skbedit_filter(), replace_skbedit_filter().
-fcoe_filter_id=`get_filter_id $real_ifname $FCOE_FILTER_KEY`
-fip_filter_id=`get_filter_id $real_ifname $FIP_FILTER_KEY`
+fcoe_filter_id=`get_filter_id $net_ifname $FCOE_FILTER_KEY`
+fip_filter_id=`get_filter_id $net_ifname $FIP_FILTER_KEY`
if [ "$qos_list" == "disable" ]; then
# Remove the FCoE filters
- find_skbedit_filter $real_ifname $FCOE_ETHERTYPE $fcoe_filter_id
+ find_skbedit_filter $net_ifname $FCOE_ETHERTYPE $fcoe_filter_id
found_filter=$?
- [ $found_filter -le 7 ] && delete_skbedit_filter $real_ifname $found_filter $FCOE_ETHERTYPE $fcoe_filter_id
+ [ $found_filter -le 7 ] && delete_skbedit_filter $net_ifname \
+ $found_filter $FCOE_ETHERTYPE $fcoe_filter_id
# Remove the FIP filters
- find_skbedit_filter $real_ifname $FIP_ETHERTYPE $fip_filter_id
+ find_skbedit_filter $net_ifname $FIP_ETHERTYPE $fip_filter_id
found_filter=$?
- [ $found_filter -le 7 ] && delete_skbedit_filter $real_ifname $found_filter $FIP_ETHERTYPE $fip_filter_id
+ [ $found_filter -le 7 ] && delete_skbedit_filter $net_ifname \
+ $found_filter $FIP_ETHERTYPE $fip_filter_id
elif [ -n $qos_list ]; then
#
@@ -287,7 +278,6 @@
*)
echo "$cmdname: bad QOS value '$1'" >&2
usage
-
;;
esac
if [ -z "$QOS_BEST" ]; then
@@ -302,7 +292,7 @@
# If the best QOS is not found, do nothing.
[ -z "$QOS_BEST" ] && exit 0
- [ ${DEBUG_LOGGING} ] && $LOGGER "$real_ifname - Choosing QOS '$QOS_BEST'"
+ [ ${DEBUG_LOGGING} ] && $LOGGER "$net_ifname - Choosing QOS '$QOS_BEST'"
#
# Setup the traffic classifier for FCoE
@@ -310,45 +300,49 @@
#
qos_queue=`expr $QOS_BEST`
- find_multiq_qdisc $real_ifname
+ find_multiq_qdisc $net_ifname
found_qdisc=$?
if [ $found_qdisc -eq 1 ]; then
# Adjust the FCoE filter
- [ ${DEBUG_LOGGING} ] && $LOGGER "$real_ifname: Qdisc is found"
- find_skbedit_filter $real_ifname $FCOE_ETHERTYPE $fcoe_filter_id
+ [ ${DEBUG_LOGGING} ] && $LOGGER "$net_ifname: Qdisc is found"
+ find_skbedit_filter $net_ifname $FCOE_ETHERTYPE $fcoe_filter_id
found_filter=$?
if [ $found_filter -gt 7 ]; then
- add_skbedit_filter $real_ifname $qdisc_id $qos_queue \
+ add_skbedit_filter $net_ifname $qdisc_id $qos_queue \
$FCOE_ETHERTYPE $fcoe_filter_id
elif [ $found_filter -ne $qos_queue ]; then
[ ${DEBUG_LOGGING} ] && $LOGGER \
- "$real_ifname: Filter is found and QOS is different"
- replace_skbedit_filter $real_ifname $qos_queue $FCOE_ETHERTYPE $fcoe_filter_id
+ "$net_ifname: Filter is found and QOS is different"
+ replace_skbedit_filter $net_ifname $qos_queue \
+ $FCOE_ETHERTYPE $fcoe_filter_id
else
[ ${DEBUG_LOGGING} ] && $LOGGER \
- "$real_ifname: Filter is found and is identical"
+ "$net_ifname: Filter is found and is identical"
fi
# Adjust the FIP filter
- [ ${DEBUG_LOGGING} ] && $LOGGER "$real_ifname: Qdisc is found"
- find_skbedit_filter $real_ifname $FIP_ETHERTYPE $fip_filter_id
+ [ ${DEBUG_LOGGING} ] && $LOGGER "$net_ifname: Qdisc is found"
+ find_skbedit_filter $net_ifname $FIP_ETHERTYPE $fip_filter_id
found_filter=$?
if [ $found_filter -gt 7 ]; then
- add_skbedit_filter $real_ifname $qdisc_id $qos_queue \
+ add_skbedit_filter $net_ifname $qdisc_id $qos_queue \
$FIP_ETHERTYPE $fip_filter_id
elif [ $found_filter -ne $qos_queue ]; then
[ ${DEBUG_LOGGING} ] && $LOGGER \
- "$ifname: Filter is found and QOS is different"
- replace_skbedit_filter $real_ifname $qos_queue $FIP_ETHERTYPE $fip_filter_id
+ "$net_ifname: Filter is found and QOS is different"
+ replace_skbedit_filter $net_ifname $qos_queue \
+ $FIP_ETHERTYPE $fip_filter_id
else
[ ${DEBUG_LOGGING} ] && $LOGGER \
- "$real_ifname: Filter is found and is identical"
+ "$net_ifname: Filter is found and is identical"
fi
else
- add_multiq_qdisc $real_ifname $qdisc_id
- add_skbedit_filter $real_ifname $qdisc_id $qos_queue $FCOE_ETHERTYPE $fcoe_filter_id
- add_skbedit_filter $real_ifname $qdisc_id $qos_queue $FIP_ETHERTYPE $fip_filter_id
+ add_multiq_qdisc $net_ifname $qdisc_id
+ add_skbedit_filter $net_ifname $qdisc_id $qos_queue \
+ $FCOE_ETHERTYPE $fcoe_filter_id
+ add_skbedit_filter $net_ifname $qdisc_id $qos_queue \
+ $FIP_ETHERTYPE $fip_filter_id
fi
fi
diff -Pur --exclude=.git fcoe-utils/fcoe_utils.h.in fcoe-utils-tip/fcoe_utils.h.in
--- fcoe-utils/fcoe_utils.h.in 1969-12-31 16:00:00.000000000 -0800
+++ fcoe-utils-tip/fcoe_utils.h.in 2010-01-08 12:15:27.549000527 -0800
@@ -0,0 +1,6 @@
+#ifndef _FCOE_UTILS_H_
+#define _FCOE_UTILS_H_
+
+#define FCOE_UTILS_VERSION "@VERSION@"
+
+#endif /* _FCOE_UTILS_H_ */
diff -Pur --exclude=.git fcoe-utils/fcrls.c fcoe-utils-tip/fcrls.c
--- fcoe-utils/fcrls.c 1969-12-31 16:00:00.000000000 -0800
+++ fcoe-utils-tip/fcrls.c 2010-01-08 12:15:27.553000527 -0800
@@ -0,0 +1,507 @@
+/*
+ * Copyright(c) 2009 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
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <linux/types.h>
+typedef __u8 u8;
+typedef __u16 u16;
+typedef __u32 u32;
+typedef __u64 u64;
+#include <linux/bsg.h>
+#include <scsi/sg.h>
+#include <scsi/fc/fc_els.h>
+#include <scsi/scsi_bsg_fc.h>
+
+#define ntoh24(n) (u32) ((n)[0] << 16 | (n)[1] << 8 | (n)[2])
+#define hton24(h) { (h) >> 16 & 0xff, (h) >> 8 & 0xff, (h) & 0xff }
+
+#define SYSFS_FC_RPORTS "/sys/class/fc_remote_ports"
+
+struct rport_info {
+ int host_no;
+ int channel;
+ u32 number;
+ u32 port_id;
+ bool found;
+ bool online;
+};
+
+struct fcoe_fc_els_lesb {
+ __be32 lesb_link_fail; /* link failure count */
+ __be32 lesb_vlink_fail; /* virtual link failure count */
+ __be32 lesb_miss_fka; /* missing FIP keep-alive count */
+ __be32 lesb_symb_err; /* symbol error during carrier count */
+ __be32 lesb_err_block; /* errored block count */
+ __be32 lesb_fcs_error; /* frame check sequence error count */
+} __attribute__((__packed__));
+
+union rls_acc {
+ struct fc_els_lesb fs3;
+ struct fcoe_fc_els_lesb bb5;
+} __attribute__((__packed__));
+
+struct rls_rjt {
+ u8 er_resv;
+ u8 er_reason;
+ u8 er_explan;
+ u8 er_vendor;
+} __attribute__((__packed__));
+
+struct rls_rsp {
+ u8 rls_cmd;
+ u8 rls_resv[3];
+ union rls_acc acc;
+ struct rls_rjt rjt;
+} __attribute__((__packed__));
+
+static char *rjt_reason[] = {
+ [1] = "Invalid command code",
+ [2] = "Invalid version level",
+ [3] = "Logical error",
+ [4] = "Invalid CT_IU size",
+ [5] = "Logical busy",
+ [7] = "Protocol error",
+ [9] = "Unable to perform command request",
+ [0xB] = "Command not supported",
+ [0xD] = "Server not available",
+ [0xE] = "Session could not be established",
+ [0xFF] = "Vendor specific",
+ [0x100] = "N/A",
+};
+
+static char *rjt_explan[] = {
+ [0] = "No additional explanation",
+ [1] = "Port Identifier not registered",
+ [2] = "Port Name not registered",
+ [3] = "Node Name not registered",
+ [4] = "Class of Service not registered",
+ [6] = "Initial Process Associator not registered",
+ [7] = "FC-4 Types not registered",
+ [8] = "Symbolic Port Name not registered",
+ [9] = "Symbolic Node Name not registered",
+ [0xA] = "Port Type not registered",
+ [0xC] = "Fabric Port Name not registered",
+ [0xD] = "Hard Address not registered",
+ [0xF] = "FC-4 Features not registered",
+ [0x10] = "Access denied",
+ [0x11] = "Unacceptable Port Identifier",
+ [0x12] = "Data base empty",
+ [0x13] = "No object registered in the specified scope",
+ [0x14] = "Domain ID not present",
+ [0x15] = "Port number not present",
+ [0x16] = "No device attached",
+ [0x17] = "invalid OX_ID-RX_ID combination",
+ [0x19] = "Request already in progress",
+ [0x1e] = "N_Port login required",
+ [0x29] = "insufficient resources",
+ [0x2a] = "unable to supply requested data",
+ [0x2c] = "Request not supported",
+ [0x2d] = "Invalid payload length",
+ [0x44] = "Invalid Port/Node_Name",
+ [0x46] = "Login Extension not supported",
+ [0x48] = "Authentication required",
+ [0x50] = "Periodic Scan Value not allowed",
+ [0x51] = "Periodic Scanning not supported",
+ [0x60] = "MAC addressing mode not supported",
+ [0x61] = "Proposed MAC address incorrectly formed",
+ [0xf0] = "Authorization Exception",
+ [0xf1] = "Authentication Exception",
+ [0xf2] = "Data base full",
+ [0xf3] = "Data base empty",
+ [0xf4] = "Processing request",
+ [0xf5] = "Unable to verify connection",
+ [0xf6] = "Devices not in a common zone",
+ [0x100] = "N/A",
+
+};
+
+enum commands {
+ NONE = 0,
+ RLS_PORT,
+ RLS_FCID,
+ RLS_QUIET,
+ RLS_HELP,
+};
+
+/* RLS_QUIET */
+static bool quiet;
+
+/* : - has arg
+ * :: - has optional arg
+ * ; - arg is long opt
+ */
+static const struct option lopt[] = {
+ { "port", required_argument, NULL, RLS_PORT },
+ { "fcid", required_argument, NULL, RLS_FCID },
+ { "quiet", no_argument, NULL, RLS_QUIET },
+ { "help", no_argument, NULL, RLS_HELP },
+ { NULL, 0, NULL, 0 },
+};
+
+static const char *lopt_usage[] = {
+ "rport bsg name, e.g., rport-7:0-1.",
+ "rport port FC_ID, e.g., 0xce000d.",
+ "disable verbose output.",
+ "print useage information.",
+ NULL,
+};
+
+#define bsg_error(format...) \
+({ \
+ fprintf(stderr, "ERROR: " format); \
+})
+
+#define bsg_debug(format...) \
+({ \
+ if (!quiet) \
+ printf("DEBUG: " format); \
+})
+
+static char *els_rjt2str(int type, int code)
+{
+ char **str;
+
+ str = (type == 0) ? rjt_reason : rjt_explan;
+
+ if (code > 0xff)
+ code = 0x100;
+
+ if (!str[code])
+ code = 0x100;
+
+ return str[code];
+}
+
+static int els_print_lesb(struct fcoe_fc_els_lesb *lesb)
+{
+ printf("RLS request accepted (LS_ACC), dumping status counters:\n"
+ "\tLink Failure Count = %u\n"
+ "\tVirtual Link Failure Count = %u\n"
+ "\tMissed Discovery Advertisement Count = %u\n"
+ "\tSymbol Error During Carrier Count = %u\n"
+ "\tErrored Block Count = %u\n"
+ "\tFrame Check Sequence Error Count = %u\n",
+ ntohl(lesb->lesb_link_fail),
+ ntohl(lesb->lesb_vlink_fail),
+ ntohl(lesb->lesb_miss_fka),
+ ntohl(lesb->lesb_symb_err),
+ ntohl(lesb->lesb_err_block),
+ ntohl(lesb->lesb_fcs_error));
+
+ return 0;
+}
+
+static int els_print_rjt(struct rls_rjt *rjt)
+{
+ printf("RLS request rejected (LS_RJT), check reason code below:\n"
+ "\tReason Code = 0x%02x, %s.\n"
+ "\tExplain Code = 0x%02x, %s.\n",
+ rjt->er_reason, els_rjt2str(0, rjt->er_reason),
+ rjt->er_explan, els_rjt2str(1, rjt->er_explan));
+ if (rjt->er_reason == ELS_RJT_VENDOR)
+ printf("\tVendor Code = 0x%02x (check with your vendor).\n",
+ rjt->er_vendor);
+ return 0;
+}
+
+static int bsg_rport_els(int bsg, u8 els_code, void *req, int req_len,
+ void *rsp, int rsp_len)
+{
+ int rc;
+ char sense[96];
+ struct fc_bsg_reply *reply = (struct fc_bsg_reply *)sense;
+ struct fc_bsg_request cdb = {
+ .msgcode = FC_BSG_RPT_ELS,
+ .rqst_data.r_els = {
+ .els_code = els_code,
+ }
+ };
+
+ struct sg_io_v4 sgio = {
+ .guard = 'Q',
+ .protocol = BSG_PROTOCOL_SCSI,
+ .subprotocol = BSG_SUB_PROTOCOL_SCSI_TRANSPORT,
+ .request_len = sizeof(cdb),
+ .request = (u64)((long)&cdb),
+ .dout_xfer_len = req_len,
+ .dout_xferp = (u64)((long)req),
+ .din_xfer_len = rsp_len,
+ .din_xferp = (u64)((long)rsp),
+ .max_response_len = sizeof(sense),
+ .response = (u64)((long)&sense),
+ .timeout = 1000,
+ };
+ memset(sense, 0, sizeof(sense));
+ rc = ioctl(bsg, SG_IO, &sgio);
+ bsg_debug("ioctl returned %d: bsg_reply result=%d\n",
+ rc, reply->result);
+ return rc;
+}
+
+static int bsg_rport_els_rls(int bsg, struct rport_info *rpi)
+{
+ int rc = EOPNOTSUPP;
+ struct fc_els_rls rls = {
+ .rls_cmd = ELS_RLS,
+ .rls_port_id = hton24(rpi->port_id),
+ };
+ struct rls_rsp rsp;
+
+ memset(&rsp, 0, sizeof(rsp));
+ rc = bsg_rport_els(bsg, ELS_RLS, &rls, sizeof(rls), &rsp, sizeof(rsp));
+ if (rc) {
+ bsg_error("bsg_rport_els(ELS_RLS) failed\n");
+ return rc;
+ }
+ if (rsp.rls_cmd == ELS_LS_ACC)
+ return els_print_lesb(&rsp.acc.bb5);
+
+ if (rsp.rls_cmd == ELS_LS_RJT)
+ return els_print_rjt(&rsp.rjt);
+
+ bsg_error("Unknow response!\n");
+ return EIO;
+}
+
+static int rport_getid(struct rport_info *rpi)
+{
+ FILE *f;
+ char rp_sysfs[256];
+
+ if (rpi->found)
+ return 0;
+ snprintf(rp_sysfs, sizeof(rp_sysfs), "%s/rport-%d:%d-%d/port_id",
+ SYSFS_FC_RPORTS, rpi->host_no, rpi->channel, rpi->number);
+ f = fopen(rp_sysfs, "ro");
+ if (!f) {
+ bsg_error("failed to fopen(%s)!\n", rp_sysfs);
+ return ENODEV;
+ }
+ if (1 != fscanf(f, "0x%6x", &rpi->port_id)) {
+ bsg_error("failed to fscanf(%s)\n", rp_sysfs);
+ fclose(f);
+ return ENODEV;
+ }
+ if (rpi->port_id & 0xff000000) {
+ bsg_error("rport %s:invalid fcid 0x%x\n", rp_sysfs,
+ rpi->port_id);
+ rpi->port_id = 0;
+ fclose(f);
+ return ENODEV;
+ }
+ fclose(f);
+ return 0;
+}
+
+/*
+ * parse a string in format of rport-%d:%d-%d, and get the
+ * corresponding rport info.
+ * rport-%d:%d-%d
+ */
+static int rport_parse(const char *s, struct rport_info *rpi)
+{
+ if (!s)
+ return EINVAL;
+ memset(rpi, 0, sizeof(*rpi));
+ if (3 != sscanf(s, "rport-%d:%d-%d", &rpi->host_no, &rpi->channel,
+ &rpi->number))
+ return ENODEV;
+ if (rport_getid(rpi))
+ return ENODEV;
+ return 0;
+}
+
+#define RPORT_ONLINE "Online"
+static int rport_check_state(struct rport_info *rpi)
+{
+ FILE *f;
+ char rp_sysfs[256];
+ char rp_state[256];
+
+ rpi->online = false;
+ if (!rpi->found)
+ return EINVAL;
+
+ snprintf(rp_sysfs, sizeof(rp_sysfs), "%s/rport-%d:%d-%d/port_state",
+ SYSFS_FC_RPORTS, rpi->host_no, rpi->channel, rpi->number);
+
+ f = fopen(rp_sysfs, "ro");
+ if (!f) {
+ bsg_error("failed to fopen(%s)!\n", rp_sysfs);
+ return ENODEV;
+ }
+ if (!fgets(rp_state, sizeof(rp_state), f)) {
+ bsg_error("failed to fgets(%s)!\n", rp_sysfs);
+ fclose(f);
+ return ENODEV;
+ }
+ if (strncmp(rp_state, RPORT_ONLINE, strlen(RPORT_ONLINE))) {
+ bsg_error("rport 0x%x %s:must be %s\n", rpi->port_id,
+ rp_state, RPORT_ONLINE);
+ fclose(f);
+ return ENODEV;
+ }
+ rpi->online = true;
+ fclose(f);
+ return 0;
+}
+/* locate rport by fcid */
+static int rport_find(struct rport_info *rpi)
+{
+ int n;
+ struct dirent **namelist;
+ struct rport_info rpii;
+
+ if (rpi->found)
+ return 0;
+
+ if (!rpi->port_id)
+ return ENODEV;
+
+ n = scandir(SYSFS_FC_RPORTS, &namelist, 0, alphasort);
+ if (n < 0) {
+ bsg_error("failed to scandir %s\n", SYSFS_FC_RPORTS);
+ return ENODEV;
+ }
+ while (n--) {
+ if (namelist[n]->d_type != DT_DIR)
+ goto free_name;
+ if (rport_parse(namelist[n]->d_name, &rpii))
+ goto free_name;
+ if (rpi->port_id != rpii.port_id)
+ goto free_name;
+ rpii.found = true;
+ memcpy(rpi, &rpii, sizeof(rpii));
+ bsg_debug("found rport 0x%06x as rport-%d:%d-%d\n",
+ rpi->port_id, rpi->host_no, rpi->channel,
+ rpi->number);
+free_name:
+ free(namelist[n]);
+ }
+ free(namelist);
+ return 0;
+}
+
+static void bsg_usage(int status)
+{
+ int i, n;
+
+ if (status)
+ bsg_error("Failed! %s (Errno %d)!\n", strerror(status), status);
+
+ n = sizeof(lopt)/sizeof(struct option) - 1;
+ printf("Usage: fcrls\n");
+ for (i = 0; i < n; i++)
+ printf("\t--%s: %s\n", lopt[i].name, lopt_usage[i]);
+ exit(status);
+}
+
+
+int main(int argc, char *argv[])
+{
+ int rc = ENODEV;
+ int opt;
+ int bsg_dev;
+ char *endptr;
+ char *bsg_name = NULL;
+ struct rport_info rpi;
+
+ rpi.found = false;
+ while ((opt = getopt_long(argc, argv, "", lopt, NULL)) != -1) {
+ switch (opt) {
+ case RLS_PORT:
+ if (rport_parse(optarg, &rpi)) {
+ bsg_error("%s format incorrect, must be:"
+ "rport-host:channel-number\n", optarg);
+ bsg_usage(EINVAL);
+ }
+ rpi.found = true;
+ goto out_rls;
+ case RLS_FCID:
+ rpi.found = false;
+ rpi.port_id = strtoull(optarg, &endptr, 16);
+ if (*endptr != '\0') {
+ bsg_error("%s has no valid FCID\n", optarg);
+ bsg_usage(EINVAL);
+ }
+ if (rport_find(&rpi)) {
+ bsg_error("%s is not a rport\n", optarg);
+ bsg_usage(ENODEV);
+ }
+ goto out_rls;
+ case RLS_QUIET:
+ quiet = true;
+ break;
+ case RLS_HELP:
+ bsg_usage(0);
+ break;
+ }
+ }
+out_rls:
+ /* bsg device name */
+ if (!rpi.found)
+ bsg_usage(ENODEV);
+
+ if (asprintf(&bsg_name, "/dev/bsg/rport-%d:%d-%d",
+ rpi.host_no, rpi.channel, rpi.number) < 0) {
+ rc = ENOMEM;
+ bsg_error("not enough memory!\n");
+ goto out_error;
+ }
+ /* open bsg device */
+ bsg_dev = open(bsg_name, O_RDWR);
+ if (bsg_dev < 0) {
+ bsg_error("failed to open %s!\n", bsg_name);
+ goto out_free;
+ }
+ /* check port state */
+ if (rport_check_state(&rpi) || (!rpi.online)) {
+ bsg_error("rport 0x%x is not online!\n", rpi.port_id);
+ goto out_close;
+ }
+ /* send rls */
+ rc = bsg_rport_els_rls(bsg_dev, &rpi);
+ if (rc) {
+ bsg_error("Faild to bsg_rport_els_rls\n");
+ goto out_close;
+ }
+ rc = 0;
+
+out_close:
+ close(bsg_dev);
+out_free:
+ free(bsg_name);
+out_error:
+ return rc;
+}
diff -Pur --exclude=.git fcoe-utils/fipvlan.c fcoe-utils-tip/fipvlan.c
--- fcoe-utils/fipvlan.c 2010-01-08 15:43:45.071000396 -0800
+++ fcoe-utils-tip/fipvlan.c 2010-01-08 12:15:27.553000527 -0800
@@ -36,6 +36,7 @@
#include <arpa/inet.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
+#include "fcoe_utils.h"
#include "fip.h"
#include "log.h"
#include "list.h"
@@ -45,7 +46,6 @@
/* global configuration */
char *exe;
-#define VERSION_STR "0.5"
struct iff {
int ifindex;
@@ -532,7 +532,7 @@
help(0);
break;
case 'v':
- printf("%s version %s\n", exe, VERSION_STR);
+ printf("%s version %s\n", exe, FCOE_UTILS_VERSION);
exit(0);
break;
default:
diff -Pur --exclude=.git fcoe-utils/.gitignore fcoe-utils-tip/.gitignore
--- fcoe-utils/.gitignore 2010-01-08 15:43:45.066000267 -0800
+++ fcoe-utils-tip/.gitignore 2010-01-08 12:15:27.543000528 -0800
@@ -15,12 +15,16 @@
# other autoconf generated files
fcoe-utils.spec
fcoeplumb
+fcoe_utils.h
# compile generated files
*.o
fcoeadm
fcoemon
fipvlan
+fcping
+fcnsq
+fcrls
etc/initd/fcoe
# build.sh generated files
diff -Pur --exclude=.git fcoe-utils/Makefile.am fcoe-utils-tip/Makefile.am
--- fcoe-utils/Makefile.am 2010-01-08 16:56:55.788000544 -0800
+++ fcoe-utils-tip/Makefile.am 2010-01-08 12:15:27.544000527 -0800
@@ -1,5 +1,5 @@
## target programs, to be built and installed in $(prefix)/sbin
-sbin_PROGRAMS = fcoeadm fcping fipvlan fcnsq
+sbin_PROGRAMS = fcoeadm fcping fipvlan fcnsq fcrls
if WITH_DCB
sbin_PROGRAMS += fcoemon
endif
@@ -12,7 +12,7 @@
## rules for building fcoeadm
## only listed sources get packaged, so must list all headers too
-fcoeadm_SOURCES = fcoeadm_display.c fcoeadm.c fcoeadm.h \
+fcoeadm_SOURCES = fcoeadm_display.c fcoeadm.c fcoeadm.h fcoe_utils.h \
include/fc_scsi.h include/fc_types.h include/net_types.h fcoe_clif.c fcoe_clif.h
## fcoeadm uses HBAAPI, so get the right flags for compiling and linking
@@ -30,7 +30,8 @@
## rules for building fcoemon
## only listed sources get packaged, so must list all headers too
fcoemon_SOURCES = fcoemon_utils.c fcoemon.c fcoemon.h fcoemon_utils.h \
-include/fc_scsi.h include/fc_types.h include/net_types.h fcoe_clif.c fcoe_clif.h
+fcoe_utils.h include/fc_scsi.h include/fc_types.h include/net_types.h \
+fcoe_clif.c fcoe_clif.h
## fcoemon needs headers from dcbd, get the right include path for them
fcoemon_CFLAGS = $(DCBD_CFLAGS)
@@ -38,7 +39,8 @@
## rules for building fipvlan
## only listed sources get packaged, so must list all headers too
-fipvlan_SOURCES = fipvlan.c include/fip.h log.c include/log.h include/list.h
+fipvlan_SOURCES = fipvlan.c fcoe_utils.h include/fip.h \
+log.c include/log.h include/list.h
## install configuration file in $(prefix)/etc/fcoe
fcoe_configdir = ${sysconfdir}/fcoe