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
openSUSE Build Service is sponsored by