File fcoe-utils-rc2-more-updates of Package open-fcoe

From 4a2faf2898866e183a722bbeca5e9ac552a5d92a Mon Sep 17 00:00:00 2001
From: Hannes Reinecke <hare@suse.de>
Date: Thu, 25 Mar 2010 13:31:24 +0100
Subject: [PATCH] More fipvlan fixes

Adding some more fipvlan fixes and these applies cleanly on top of last
attached patches.

I'm resync-ing with open-fcoe top commit
a2d4f4516acf23b5c0c9bd703df8772052be3d81 plus some more pending fipvlan patches
for open-fcoe, pending patches needed when using fipvlan from initrd.

References: bnc#590324

Signed-off-by: Vasu Dev <vasu.dev@linux.intel.com>
Acked-by: Hannes Reinecke <hare@suse.de>

diff --git a/Makefile.am b/Makefile.am
index bdd510f..811c301 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,63 +1,50 @@
-# build libutil first
-SUBDIRS = lib .
-
 ## target programs, to be built and installed in $(prefix)/sbin
-sbin_PROGRAMS = fcoeadm fcping fipvlan fcnsq fcrls
-if WITH_DCB
-sbin_PROGRAMS += fcoemon
-endif
+sbin_PROGRAMS = fcoeadm fcoemon fcping fipvlan fcnsq fcrls
 
 ## all targets should look for headers in the include directory
-AM_CPPFLAGS = -Wall -I${srcdir}/include
-
+AM_CPPFLAGS = -I${srcdir}/include -I${builddir}/include
 ## pass the sysconfdir into the C proprocessor
-AM_CFLAGS = -DSYSCONFDIR="\"${sysconfdir}\""
+AM_CPPFLAGS += -DSYSCONFDIR="\"${sysconfdir}\""
+AM_CFLAGS = -Wall
 
 ## rules for building fcoeadm
-## only listed sources get packaged, so must list all headers too
-fcoeadm_SOURCES = fcoeadm_display.c fcoeadm.c fcoeadm.h \
-include/fc_scsi.h include/fc_types.h \
-include/net_types.h fcoe_clif.h
+fcoeadm_SOURCES = fcoeadm.c fcoeadm_display.c
 fcoeadm_LDADD = lib/libutil.a
+fcoeadm_CFLAGS = $(AM_CFLAGS) $(HBAAPI_CFLAGS)
+fcoeadm_LDFLAGS = $(AM_LDFLAGS) $(HBAAPI_LIBS)
 
-## fcoeadm uses HBAAPI, so get the right flags for compiling and linking
-fcoeadm_CFLAGS = $(HBAAPI_CFLAGS)
-fcoeadm_LDFLAGS = $(HBAAPI_LIBS)
+## rules for building fcoemon
+fcoemon_SOURCES = fcoemon.c
+fcoemon_LDADD = lib/libutil.a
+fcoemon_CFLAGS = $(AM_CFLAGS) $(DCBD_CFLAGS)
+fcoemon_LDFLAGS = $(AM_LDFLAGS) -lrt
 
 ## rules for building fcping
-## only listed sources get packaged, so must list all headers too
 fcping_SOURCES = fcping.c
 fcping_LDADD = lib/libutil.a
-
-## fcping uses HBAAPI, so get the right flags for compiling and linking
-fcping_CFLAGS = $(HBAAPI_CFLAGS)
-fcping_LDFLAGS = $(HBAAPI_LIBS) -lrt
-
-## rules for building fcoemon
-## only listed sources get packaged, so must list all headers too
-fcoemon_SOURCES = fcoemon.c fcoemon.h \
-include/fc_scsi.h \
-include/fc_types.h include/net_types.h fcoe_clif.h
-fcoemon_LDADD = lib/libutil.a
-
-## fcoemon needs headers from dcbd, get the right include path for them
-fcoemon_CFLAGS = $(DCBD_CFLAGS)
-fcoemon_LDFLAGS = -lrt
+fcping_CFLAGS = $(AM_CFLAGS) $(HBAAPI_CFLAGS)
+fcping_LDFLAGS = $(AM_LDFLAGS) $(HBAAPI_LIBS) -lrt
 
 ## rules for building fipvlan
-## only listed sources get packaged, so must list all headers too
-fipvlan_SOURCES = fipvlan.c include/fip.h
+fipvlan_SOURCES = fipvlan.c
 fipvlan_LDADD = lib/libutil.a
 
+AUTOMAKE_OPTIONS=subdir-objects
+noinst_LIBRARIES = lib/libutil.a
+lib_libutil_a_SOURCES = lib/fcoe_utils.c lib/sa_log.c lib/sa_select.c \
+	lib/sa_timer.c lib/sa_other.c lib/fip.c lib/rtnetlink.c
+
+## header files that need to be distributed
+noinst_HEADERS = fcoeadm_display.h fcoe_clif.h fcoemon.h \
+	include/fcoemon_utils.h include/fcoe_utils.h include/fc_scsi.h \
+	include/fc_types.h include/fip.h include/net_types.h include/rtnetlink.h
+
 ## install configuration file in $(prefix)/etc/fcoe
 fcoe_configdir = ${sysconfdir}/fcoe
 dist_fcoe_config_DATA = etc/cfg-ethx
 
 ## man pages for fcoeadm and fcoemon
-dist_man_MANS = doc/fcoeadm.8
-if WITH_DCB
-dist_man_MANS += doc/fcoemon.8
-endif
+dist_man_MANS = doc/fcoeadm.8 doc/fcoemon.8
 
 ## init script for fcoemon
 dist_noinst_SCRIPTS = etc/initd/initd.suse etc/initd/initd.fedora
@@ -74,9 +61,9 @@ etc/initd/fcoe:
 init_ddir = ${sysconfdir}/init.d
 init_d_SCRIPTS = etc/initd/fcoe
 
-dist_noinst_DATA = README COPYING INSTALL fcoe-utils.spec
+dist_noinst_DATA = README COPYING INSTALL fcoe-utils.spec etc/config
 
 install-data-hook:
 	if [ ! -f ${DESTDIR}${fcoe_configdir}/config ] ; then \
-		cp etc/config ${DESTDIR}${fcoe_configdir}/config; \
+ 		cp ${srcdir}/etc/config ${DESTDIR}${fcoe_configdir}/config; \
 	fi
diff --git a/configure.ac b/configure.ac
index db4e55c..a0f9c91 100644
--- a/configure.ac
+++ b/configure.ac
@@ -9,17 +9,9 @@ PKG_CHECK_MODULES([HBAAPI], [HBAAPI])
 AC_SUBST([HBAAPI_CFLAGS])
 AC_SUBST([HBAAPI_LIBS])
 
-AC_ARG_WITH([dcb],
-	[AS_HELP_STRING([--without-dcb], [disable DCB support])],
-	[],
-	[with_dcb=yes])
+PKG_CHECK_MODULES([DCBD], [dcbd])
+AC_SUBST([DCBD_CFLAGS])
 
-AM_CONDITIONAL([WITH_DCB], [test "X$with_dcb" != Xno])
-
-AS_IF([test "X$with_dcb" != Xno],
-	[PKG_CHECK_MODULES([DCBD], [dcbd])
-	AC_SUBST([DCBD_CFLAGS])])
-
-AC_CONFIG_FILES([Makefile lib/Makefile fcoe-utils.spec include/fcoe_utils_version.h])
+AC_CONFIG_FILES([Makefile fcoe-utils.spec include/fcoe_utils_version.h])
 AC_OUTPUT
 
diff --git a/contrib/fcoe-setup.sh b/contrib/fcoe-setup.sh
old mode 100755
new mode 100644
diff --git a/contrib/sysfs_edd.sh b/contrib/sysfs_edd.sh
index 1f14f1b..d710561 100755
--- a/contrib/sysfs_edd.sh
+++ b/contrib/sysfs_edd.sh
@@ -6,47 +6,229 @@
 # with more options as we progress further.
 #
 # Author: Supreeth Venkataraman
+#	  Yi Zou
 #         Intel Corporation
 #
-# Usage: edd.sh -i for getting the interface name.
-#        edd.sh -t for getting target information.
-#        edd.sh -h for displaying help information.
+# Usage: sysfs_edd.sh -t for getting FCoE boot target information.
+#        sysfs_edd.sh -i for getting FCoE boot NIC name.
+#        sysfs_edd.sh -m for getting FCoE boot NIC MAC.
+#        sysfs_edd.sh -e for getting FCoE boot EDD information.
+#        sysfs_edd.sh -r for getting FCoE boot EDD interface type and path.
+#        sysfs_edd.sh -a for getting all FCoE boot information.
+#        sysfs_edd.sh -h for usage information.
+#        Optional: use -v to turn on verbose mode.
+#
+# Notes:
+# FCoE Boot Disk is identified by the following format of boot information
+# in its corresponding sysfs firmware edd entry, i.e.,
+# 	/sys/firmware/edd/int13_dev??/interface
+# which is formatted as (for FCoE):
+# string format: FIBRE wwid: 8c1342b8a0001620 lun: 7f00
+# Please ref. to T13 BIOS Enhanced Disk Drive Specification v3.0 for more
+# defails on EDD.
+#
+
+SYSEDD=/sys/firmware/edd
+PREFIX="FIBRE"
+VERBOSE=
+FCOE_INF=
+FCOE_WWN=
+FCOE_LUN=
+FCOE_EDD=
+FCOE_NIC=
+FCOE_MAC=
 
-DisplayHelp(){
-  echo "Usage: sysfs_edd.sh -i for getting the interface name."
-  echo "       sysfs_edd.sh -t for getting target information."
-  echo "       sysfs_edd.sh -h for displaying help options."
-  exit;
+
+#
+#
+#
+LOG() {
+	if [ -n "$1" ] && [ -n "${VERBOSE}" ]; then
+		echo "LOG:$1"
+	fi
 }
 
-GetTargetInfo(){
-   if [ -e /sys/firmware/edd/int13_dev80/interface ]; then
-      cd -P /sys/firmware/edd/int13_dev80
-   else
-      echo "Target information not found in EDD!"; exit;
-   fi
 
-   line=`cat interface`;
-   echo $line;
+find_fcoe_boot_disk() {
+	local prefix=
+
+	if [ ! -e $SYSEDD ]; then
+		LOG "Need kernel EDD support!"
+		return 1
+	fi
+#	for disk in `find ${SYSEDD} -maxdepth 1 -name 'int13*'`
+	for disk in ${SYSEDD}/int13_*
+	do
+		LOG " checking $disk..."
+		if [ ! -e ${disk}/interface ]; then
+			continue;
+		fi
+		LOG " checking ${disk}/interface..."
+		prefix=`awk '{printf $1}' < ${disk}/interface`
+		if [ "${PREFIX}" != "${prefix}" ]; then
+			LOG " The FCoE Boot prefix ${FCOE_PRE} is invalid!"
+			continue;
+		fi
+		FCOE_INF=`cat ${disk}/interface`
+		LOG " found FCoE boot info. from boot rom:${FCOE_INF}..."
+
+		FCOE_WWN=`awk '{printf $3}' < ${disk}/interface`
+		if [ ${#FCOE_WWN} -ne 16 ]; then
+			LOG " The FCoE Boot WWID ${FCOE_WWN} is invalid!"
+			continue;
+		fi
+		FCOE_LUN=`awk '{printf $5}' < ${disk}/interface`
+		if [ -z "${#FCOE_LUN}" ]; then
+			LOG " The FCoE Boot LUN ${FCOE_WWN} is invalid!"
+			continue;
+		fi
+		# look for the correponding nic
+		# FIXME:
+		# 1) only supporst PCI device?
+		# 2) at initrd time, the nic name is always eth*?
+		if [ ! -e ${disk}/pci_dev ]; then
+			LOG "Failed to locate the corresponing PCI device!"
+			continue;
+		fi
+		if [ ! -e ${disk}/pci_dev/net ]; then
+			LOG "Failed to detect any NIC device!"
+			continue;
+		fi
+
+		for nic in ${disk}/pci_dev/net/*
+		do
+			if [ -e ${nic}/address ]; then
+				FCOE_MAC=`cat ${nic}/address`
+				FCOE_NIC=$(basename ${nic})
+				break;
+			fi
+		done
+		if [ -z "${FCOE_MAC}" ] || [ -z "${FCOE_NIC}" ]; then
+			LOG "Failed to locate the corresponing NIC device!"
+			continue;
+		fi
+		# Found the FCoE Boot Device
+		FCOE_EDD=$(basename ${disk})
+		return 0;
+	done
+	return 1
 }
 
+get_fcoe_boot_all(){
+	echo "### FCoE Boot Information ###"
+	echo "EDD=${FCOE_EDD}"
+	echo "INF=${FCOE_INF}"
+	echo "WWN=${FCOE_WWN}"
+	echo "LUN=${FCOE_LUN}"
+	echo "NIC=${FCOE_NIC}"
+	echo "MAC=${FCOE_MAC}"
+	return 0
+}
 
-GetFcoeIfName(){
-   if [ -e /sys/firmware/edd/int13_dev80/pci_dev ]; then
-        cd -P /sys/firmware/edd/int13_dev80/pci_dev
-   else
-      echo "Disk 80 not found in EDD!"; exit;
-   fi
+get_fcoe_boot_target() {
+	if [ -z "${FCOE_WWN}" ] || [ -z "${FCOE_LUN}" ]; then
+		LOG "No FCoE Boot Target information is found!"
+		return 1
+	fi
+	echo "WWN=${FCOE_WWN}"
+	echo "LUN=${FCOE_LUN}"
+}
+
+get_fcoe_boot_inf(){
+	if [ -z "${FCOE_INF}" ]; then
+		LOG "No FCoE Boot INF information is found!"
+		return 1
+	fi
+	echo "INF=${FCOE_INF}"
+	return 0
+}
+
+get_fcoe_boot_mac(){
+	if [ -z "${FCOE_MAC}" ]; then
+		LOG "No FCoE Boot NIC MAC information is found!"
+		return 1
+	fi
+	echo "MAC=${FCOE_MAC}"
+	return 0
+}
 
-   for if in net/eth* ;
-   do [ -d $if ] && echo ${if##*/}; done
+get_fcoe_boot_ifname(){
+	if [ -z "${FCOE_NIC}" ]; then
+		LOG "No FCoE Boot NIC information is found!"
+		return 1
+	fi
+	echo "NIC=${FCOE_NIC}"
+	return 0
 }
 
-while getopts ith OptionName; do
+get_fcoe_boot_edd(){
+	if [ -z "${FCOE_EDD}" ]; then
+		LOG "No FCoE Boot Disk EDD information is found!"
+		return 1
+	fi
+	echo "EDD=${FCOE_EDD}"
+	return 0
+}
+
+
+# parse options
+prog=$(basename $0)
+while getopts "timeravh" OptionName; do
     case "$OptionName" in
-        t) GetTargetInfo;;
-        i) GetFcoeIfName;;
-        h) DisplayHelp;;
-        *) echo "Invalid Option. Use -h option for help.";;
+        t)
+		action=get_fcoe_boot_target
+		;;
+        i)
+		action=get_fcoe_boot_ifname
+		;;
+        m)
+		action=get_fcoe_boot_mac
+		;;
+        e)
+		action=get_fcoe_boot_edd
+		;;
+        r)
+		action=get_fcoe_boot_inf
+		;;
+	a)
+		action=get_fcoe_boot_all
+		;;
+	v)
+		VERBOSE="yes"
+		;;
+        h)
+		echo "Usage: ${prog} -t for getting FCoE boot target information."
+		echo "       ${prog} -i for getting FCoE boot NIC name."
+		echo "       ${prog} -m for getting FCoE boot NIC MAC."
+		echo "       ${prog} -e for getting FCoE boot EDD information."
+		echo "       ${prog} -r for getting FCoE boot EDD interface type and path."
+		echo "       ${prog} -a for getting all FCoE boot information."
+		echo "       ${prog} -h for usage information."
+		echo "       Optional: use -v to turn on verbose mode."
+		exit 0
+		;;
+        *)
+		echo "Invalid Option. Use -h option for help."
+		exit 1
+		;;
     esac
 done
+if [ -z "${action}" ]; then
+	echo "Must specify at least -t, -i, -m, -e, -r, -a, or -h."
+	echo "Use -h option for help."
+	exit 1
+fi
+# Locate FCoE boot disk and nic information
+find_fcoe_boot_disk
+if [ $? -ne 0 ]; then
+	echo "No FCoE boot disk information is found in EDD!"
+	exit 1
+fi
+if [ -z "${FCOE_EDD}" ]; then
+	echo "No FCoE boot disk is found in EDD!"
+	exit 1;
+fi
+
+${action}
+
+exit $?
diff --git a/fcoemon.c b/fcoemon.c
index 259af06..d6a8fd0 100644
--- a/fcoemon.c
+++ b/fcoemon.c
@@ -94,6 +94,10 @@
 #define FCOE_ENABLE 	SYSFS_FCOE "/enable"
 #define FCOE_DISABLE	SYSFS_FCOE "/disable"
 
+#define FCM_VLAN_DISC_TIMEOUT	(1000 * 1000)	/* 1 seconds */
+#define FCM_VLAN_DISC_MAX	10		/* stop after 10 attempts */
+void fcm_vlan_disc_timeout(void *arg);
+
 enum fcm_srv_status {
 	fcm_success = 0,
 	fcm_fail,
@@ -124,6 +128,8 @@ struct fcoe_port {
 
 	int ifindex;
 	unsigned char mac[ETHER_ADDR_LEN];
+	struct sa_timer vlan_disc_timer;
+	int vlan_disc_count;
 };
 
 enum fcoeport_ifname {
@@ -290,6 +296,7 @@ static struct fcoe_port *alloc_fcoe_port(char *ifname)
 		 * that the interface is not created yet.
 		 */
 		p->last_action = FCP_DESTROY_IF;
+		sa_timer_init(&p->vlan_disc_timer, fcm_vlan_disc_timeout, p);
 	}
 
 	return p;
@@ -514,18 +521,21 @@ int fcm_vlan_disc_handler(struct fiphdr *fh, struct sockaddr_ll *sa, void *arg)
 	unsigned char mac[ETHER_ADDR_LEN];
 	int len = ntohs(fh->fip_desc_len);
 	struct fip_tlv_hdr *tlv = (struct fip_tlv_hdr *)(fh + 1);
+	char ifname[IFNAMSIZ];
+	struct fcoe_port *p;
 
-	FCM_LOG_DBG("%s", __func__);
-
-	if (ntohs(fh->fip_proto) != FIP_PROTO_VLAN) {
-		FCM_LOG_DBG("ignoring FIP frame that is not of type VLAN");
+	if (ntohs(fh->fip_proto) != FIP_PROTO_VLAN)
 		return -1;
-	}
 
-	if (fh->fip_subcode != FIP_VLAN_NOTE) {
-		FCM_LOG_DBG("ignoring FIP VLAN Discovery Request");
+	if (fh->fip_subcode != FIP_VLAN_NOTE)
 		return -1;
-	}
+
+	/* cancel the retry timer, response received */
+	rtnl_get_linkname(sa->sll_ifindex, ifname);
+	p = fcm_find_fcoe_port(ifname, FCP_CFG_IFNAME);
+	if (!p)
+		return -ENODEV;
+	sa_timer_cancel(&p->vlan_disc_timer);
 
 	while (len > 0) {
 		switch (tlv->tlv_type) {
@@ -735,6 +745,12 @@ static void fcp_set_next_action(struct fcoe_port *p, enum fcp_action action)
 		break;
 	case FCP_VLAN_DISC:
 		switch (action) {
+		case FCP_ACTIVATE_IF:
+			if (p->auto_vlan)
+				p->action = FCP_WAIT;
+			else
+				p->action = FCP_CREATE_IF;
+			break;
 		case FCP_DESTROY_IF:
 		case FCP_DISABLE_IF:
 		case FCP_RESET_IF:
@@ -1944,10 +1960,29 @@ err_out:
 	return ret;
 }
 
+void fcm_vlan_disc_timeout(void *arg)
+{
+	struct fcoe_port *p = arg;
+	FCM_LOG_DBG("%s: VLAN discovery TIMEOUT [%d]",
+		    p->ifname, p->vlan_disc_count);
+	if (++(p->vlan_disc_count) > FCM_VLAN_DISC_MAX) {
+		FCM_LOG("%s: VLAN discovery failed after %d attempts",
+			p->ifname, FCM_VLAN_DISC_MAX);
+		FCM_LOG("%s: disabling VLAN discovery, trying FCoE on %s",
+			p->ifname, p->ifname);
+		p->auto_vlan = 0;
+		fcp_set_next_action(p, FCP_ACTIVATE_IF);
+		return;
+	}
+	fip_send_vlan_request(fcm_fip_socket, p->ifindex, p->mac);
+	sa_timer_set(&p->vlan_disc_timer, FCM_VLAN_DISC_TIMEOUT);
+}
+
 int fcm_start_vlan_disc(struct fcoe_port *p)
 {
-	FCM_LOG_DBG("%s", __func__);
+	p->vlan_disc_count = 1;
 	fip_send_vlan_request(fcm_fip_socket, p->ifindex, p->mac);
+	sa_timer_set(&p->vlan_disc_timer, FCM_VLAN_DISC_TIMEOUT);
 	return 0;
 }
 
diff --git a/fipvlan.c b/fipvlan.c
index 5b428e2..1f5556b 100644
--- a/fipvlan.c
+++ b/fipvlan.c
@@ -79,8 +79,11 @@ struct iff {
 	int iflink;
 	char ifname[IFNAMSIZ];
 	unsigned char mac_addr[ETHER_ADDR_LEN];
+	bool running;
 	bool is_vlan;
 	short int vid;
+	bool req_sent;
+	bool resp_recv;
 	TAILQ_ENTRY(iff) list_node;
 	struct iff_list_head vlans;
 };
@@ -194,6 +197,7 @@ int fip_recv_vlan_note(struct fiphdr *fh, int ifindex)
 {
 	struct fip_tlv_ptrs tlvs;
 	struct fcf *fcf;
+	struct iff *iff;
 	unsigned int bitmap, required_tlvs;
 	int len;
 	int i;
@@ -208,6 +212,10 @@ int fip_recv_vlan_note(struct fiphdr *fh, int ifindex)
 	if ((bitmap & required_tlvs) != required_tlvs)
 		return -1;
 
+	iff = lookup_iff(ifindex, NULL);
+	if (iff)
+		iff->resp_recv = true;
+
 	for (i = 0; i < tlvs.vlanc; i++) {
 		fcf = malloc(sizeof(*fcf));
 		if (!fcf) {
@@ -266,6 +274,13 @@ void rtnl_recv_newlink(struct nlmsghdr *nh)
 	if (ifm->ifi_type != ARPHRD_ETHER)
 		return;
 
+	iff = lookup_iff(ifm->ifi_index, NULL);
+	if (iff) {
+		/* already tracking, update operstate and return */
+		iff->running = (ifm->ifi_flags & IFF_RUNNING) == IFF_RUNNING;
+		return;
+	}
+
 	iff = malloc(sizeof(*iff));
 	if (!iff) {
 		FIP_LOG_ERRNO("malloc failed");
@@ -277,6 +292,7 @@ void rtnl_recv_newlink(struct nlmsghdr *nh)
 	parse_ifinfo(ifla, nh);
 
 	iff->ifindex = ifm->ifi_index;
+	iff->running = (ifm->ifi_flags & IFF_RUNNING) == IFF_RUNNING;
 	if (ifla[IFLA_LINK])
 		iff->iflink = *(int *)RTA_DATA(ifla[IFLA_LINK]);
 	else
@@ -391,18 +407,18 @@ void create_missing_vlans()
 		return;
 
 	TAILQ_FOREACH(fcf, &fcfs, list_node) {
-		vlan = lookup_vlan(fcf->ifindex, fcf->vlan);
-		if (vlan) {
-			FIP_LOG_DBG("VLAN %s.%d already exists as %s",
-				    fcf->ifindex, fcf->vlan, vlan->ifname);
-			continue;
-		}
 		real_dev = lookup_iff(fcf->ifindex, NULL);
 		if (!real_dev) {
 			FIP_LOG_ERR(ENODEV, "lost device %d with discoved FCF?",
 				    fcf->ifindex);
 			continue;
 		}
+		vlan = lookup_vlan(fcf->ifindex, fcf->vlan);
+		if (vlan) {
+			FIP_LOG_DBG("VLAN %s.%d already exists as %s",
+				    real_dev->ifname, fcf->vlan, vlan->ifname);
+			continue;
+		}
 		snprintf(vlan_name, IFNAMSIZ, "%s.%d-fcoe",
 			 real_dev->ifname, fcf->vlan);
 		rc = vlan_create(fcf->ifindex, fcf->vlan, vlan_name);
@@ -472,10 +488,7 @@ void print_results()
 	printf("\n");
 }
 
-/* exit after waiting 1 second without receiving anything */
-#define TIMEOUT 1000
-
-void recv_loop(int ns, int ps)
+void recv_loop(int ns, int ps, int timeout)
 {
 	struct pollfd pfd[2] = {
 		[0].fd = ns,
@@ -486,7 +499,7 @@ void recv_loop(int ns, int ps)
 	int rc;
 
 	while (1) {
-		rc = poll(pfd, ARRAY_SIZE(pfd), TIMEOUT);
+		rc = poll(pfd, ARRAY_SIZE(pfd), timeout);
 		FIP_LOG_DBG("return from poll %d", rc);
 		if (rc == 0) /* timeout */
 			break;
@@ -509,22 +522,67 @@ void find_interfaces(int ns)
 	rtnl_recv(ns, rtnl_listener_handler, NULL);
 }
 
-void send_vlan_requests(int ps)
+int send_vlan_requests(int ps)
 {
 	struct iff *iff;
 	int i;
+	int skipped = 0;
 
 	if (config.automode) {
-		TAILQ_FOREACH(iff, &interfaces, list_node)
+		TAILQ_FOREACH(iff, &interfaces, list_node) {
+			if (iff->resp_recv)
+				continue;
+			if (!iff->running) {
+				skipped++;
+				iff->req_sent = false;
+				continue;
+			}
 			fip_send_vlan_request(ps, iff->ifindex, iff->mac_addr);
+			iff->req_sent = true;
+		}
 	} else {
 		for (i = 0; i < config.namec; i++) {
 			iff = lookup_iff(0, config.namev[i]);
-			if (!iff)
+			if (!iff) {
+				skipped++;
 				continue;
+			}
+			if (iff->resp_recv)
+				continue;
+			if (!iff->running) {
+				skipped++;
+				iff->req_sent = false;
+				continue;
+			}
 			fip_send_vlan_request(ps, iff->ifindex, iff->mac_addr);
+			iff->req_sent = true;
 		}
 	}
+	return skipped;
+}
+
+void do_vlan_discovery(ns, ps)
+{
+	struct iff *iff;
+	int retry_count = 0;
+	int skip_retry_count = 0;
+	int skipped = 0;
+retry:
+	skipped += send_vlan_requests(ps);
+	if (skipped && skip_retry_count++ < 30) {
+		FIP_LOG_DBG("waiting for IFF_RUNNING [%d]\n", skip_retry_count);
+		recv_loop(ns, ps, 500);
+		skipped = 0;
+		retry_count = 0;
+		goto retry;
+	}
+	recv_loop(ns, ps, 200);
+	TAILQ_FOREACH(iff, &interfaces, list_node)
+		/* if we did not receive a response, retry */
+		if (iff->req_sent && !iff->resp_recv && retry_count++ < 10) {
+			FIP_LOG_DBG("VLAN discovery RETRY [%d]", retry_count);
+			goto retry;
+		}
 }
 
 int main(int argc, char **argv)
@@ -562,8 +620,7 @@ int main(int argc, char **argv)
 		exit(1);
 	}
 
-	send_vlan_requests(ps);
-	recv_loop(ns, ps);
+	do_vlan_discovery(ns, ps);
 
 	print_results();
 	if (config.create) {
@@ -572,7 +629,7 @@ int main(int argc, char **argv)
 		 * need to listen for the RTM_NETLINK messages
 		 * about the new VLAN devices
 		 */
-		recv_loop(ns, ps);
+		recv_loop(ns, ps, 500);
 	}
 	if (config.start)
 		start_fcoe();
diff --git a/lib/Makefile.am b/lib/Makefile.am
deleted file mode 100644
index ebe259f..0000000
--- a/lib/Makefile.am
+++ /dev/null
@@ -1,3 +0,0 @@
-AM_CPPFLAGS = -I${top_srcdir}/include
-noinst_LIBRARIES = libutil.a
-libutil_a_SOURCES = fcoe_utils.c sa_log.c sa_select.c sa_timer.c sa_other.c fip.c rtnetlink.c
diff --git a/lib/fip.c b/lib/fip.c
index a5430c9..b0bf07d 100644
--- a/lib/fip.c
+++ b/lib/fip.c
@@ -128,8 +128,6 @@ int fip_recv(int s, fip_handler *fn, void *arg)
 	struct fiphdr *fh;
 	ssize_t len, desc_len;
 
-	FIP_LOG_DBG("%s", __func__);
-
 	len = recvmsg(s, &msg, 0);
 	if (len < 0) {
 		FIP_LOG_ERRNO("packet socket recv error");
diff --git a/lib/rtnetlink.c b/lib/rtnetlink.c
index b7a32f2..a8a8b0c 100644
--- a/lib/rtnetlink.c
+++ b/lib/rtnetlink.c
@@ -122,7 +122,6 @@ int rtnl_recv(int s, rtnl_handler *fn, void *arg)
 	int rc = 0;
 	bool more = false;
 
-	RTNL_LOG_DBG("%s", __func__);
 more:
 	len = recv(s, buf, sizeof(buf), 0);
 	if (len < 0) {
openSUSE Build Service is sponsored by