Blame SOURCES/fcoe-utils-1.0.29-29-g9267509.patch

ebec02
sync to v1.0.29-29-g9267509
ebec02
ebec02
9267509 fcoeadm: display strings for new port speeds
ebec02
671b7f9 fcoemon: Fix IEEE state machine
ebec02
4982e60 man: Fix typo in fcoemon documentation
ebec02
f90bbd7 FIPVLAN: Really break out of the recv_loop upon fip_recv error
ebec02
fa308a6 doc: Update QUICKSTART/INSTALL docs for systemd init file install
ebec02
09caead fcoemon: systemd socket activation
ebec02
41e9d79 fcoemon: add systemd service file
ebec02
d8deef2 fcnsq: Fixup 64bit integer handling
ebec02
6750b2a fcnsq: Fixup help text
ebec02
e566b3e Fix integer formatting
ebec02
9869390 build: Fix build with '-Wl,--as-needed'
ebec02
0e5d536 build: Add missing 'DESTDIR' when installing bash completion
ebec02
6bde8d1 fipvlan: filter interfaces from rtnl_getlink
ebec02
45d0e70 fipvlan: handle errors from fip socket creation
ebec02
78ea81a fipvlan: break out of receive loop on error
ebec02
86928f2 fipvlan: Do not shut down FCoE connections on physical interface
ebec02
08d9872 fipvlan: Update manpage to reflect correct timeout
ebec02
0559d7d fipvlan: Leave link up if requested
ebec02
9ade5c6 fipvlan: update manpage
ebec02
3ded166 fipvlan: Re-send VLAN discovery
ebec02
9f5e376 fipvlan: Update wait loop to wait for VLANs
ebec02
16e421a fipvlan: Start FCoE from netlink handler
ebec02
ac1fc20 fipvlan: create VLANs from netlink handler
ebec02
6ce709f fipvlan: Extract create_missing_vlan function from loop
ebec02
ef209fd fipvlan: start VLAN interface from netlink handler
ebec02
29d1722 fipvlan: Only shutdown interfaces if no vlans are created
ebec02
921a055 fipvlan fails on powerpc
ebec02
0f63a3e Don't call AM_INIT_AUTOMAKE twice
ebec02
fd085bc man: Fix small typo regarding --fcf option
ebec02
---
ebec02
 INSTALL                    |   3 +
ebec02
 Makefile.am                |  16 ++-
ebec02
 QUICKSTART                 |   3 +
ebec02
 configure.ac               |   9 +-
ebec02
 doc/fcoeadm.8              |  18 +--
ebec02
 doc/fcoeadm.txt            |   4 +-
ebec02
 doc/fcoemon.8              |   2 +-
ebec02
 doc/fcoemon.txt            |   3 +-
ebec02
 doc/fipvlan.8              |  17 ++-
ebec02
 doc/fipvlan.txt            |   9 +-
ebec02
 etc/systemd/fcoe.service   |  14 ++
ebec02
 etc/systemd/fcoemon.socket |   6 +
ebec02
 fcnsq.c                    |  20 ++-
ebec02
 fcoeadm_display.c          |  10 +-
ebec02
 fcoemon.c                  | 100 ++++++++++++--
ebec02
 fcping.c                   |  11 +-
ebec02
 fipvlan.c                  | 327 ++++++++++++++++++++++++++-------------------
ebec02
 lib/fip.c                  |  20 ++-
ebec02
 18 files changed, 394 insertions(+), 198 deletions(-)
ebec02
ebec02
diff --git a/INSTALL b/INSTALL
ebec02
index 3abdf07..ea8c95e 100644
ebec02
--- a/INSTALL
ebec02
+++ b/INSTALL
ebec02
@@ -19,6 +19,9 @@ DEPENDENCIES
ebec02
 
ebec02
 1) Bootstrap, configure, make and make install
ebec02
    # ./bootstrap.sh
ebec02
+   Either execute the next line for System V init script install
ebec02
    # rpm --eval "%configure" | sh
ebec02
+   or the following line to install systemd unit scripts
ebec02
+   # rpm --eval "%configure --with-systemdsystemunitdir=/" | sh
ebec02
    # make
ebec02
    # make install
ebec02
diff --git a/Makefile.am b/Makefile.am
ebec02
index 5cbc15f..e7df6f5 100644
ebec02
--- a/Makefile.am
ebec02
+++ b/Makefile.am
ebec02
@@ -9,21 +9,18 @@ AM_CFLAGS = -Wall -Wformat=2 -Werror -Wmissing-prototypes -Wstrict-prototypes
ebec02
 
ebec02
 ## rules for building fcoeadm
ebec02
 fcoeadm_SOURCES = fcoeadm.c fcoeadm_display.c
ebec02
-fcoeadm_LDADD = lib/libutil.a libopenfcoe.a
ebec02
+fcoeadm_LDADD = lib/libutil.a libopenfcoe.a $(HBAAPI_LIBS)
ebec02
 fcoeadm_CFLAGS = $(AM_CFLAGS) $(HBAAPI_CFLAGS)
ebec02
-fcoeadm_LDFLAGS = $(AM_LDFLAGS) $(HBAAPI_LIBS)
ebec02
 
ebec02
 ## rules for building fcoemon
ebec02
 fcoemon_SOURCES = fcoemon.c
ebec02
-fcoemon_LDADD = lib/libutil.a
ebec02
+fcoemon_LDADD = lib/libutil.a -lrt
ebec02
 fcoemon_CFLAGS = $(AM_CFLAGS) $(DCBD_CFLAGS)
ebec02
-fcoemon_LDFLAGS = $(AM_LDFLAGS) -lrt
ebec02
 
ebec02
 ## rules for building fcping
ebec02
 fcping_SOURCES = fcping.c
ebec02
-fcping_LDADD = lib/libutil.a
ebec02
+fcping_LDADD = lib/libutil.a $(HBAAPI_LIBS) -lrt
ebec02
 fcping_CFLAGS = $(AM_CFLAGS) $(HBAAPI_CFLAGS)
ebec02
-fcping_LDFLAGS = $(AM_LDFLAGS) $(HBAAPI_LIBS) -lrt
ebec02
 
ebec02
 ## rules for building fipvlan
ebec02
 fipvlan_SOURCES = fipvlan.c
ebec02
@@ -44,6 +41,11 @@ noinst_HEADERS = fcoeadm_display.h fcoe_clif.h fcoemon.h \
ebec02
 fcoe_configdir = ${sysconfdir}/fcoe
ebec02
 dist_fcoe_config_DATA = etc/cfg-ethx
ebec02
 
ebec02
+## install systemd service files
ebec02
+if HAVE_SYSTEMD
ebec02
+systemdsystemunit_DATA = etc/systemd/fcoe.service etc/systemd/fcoemon.socket
ebec02
+endif
ebec02
+
ebec02
 ## man pages for fcoeadm and fcoemon
ebec02
 dist_man_MANS = doc/fcoeadm.8 doc/fcoemon.8 doc/fipvlan.8 doc/fcrls.8 \
ebec02
 	doc/fcnsq.8 doc/fcping.8
ebec02
@@ -67,7 +69,7 @@ init_d_SCRIPTS = etc/initd/fcoe
ebec02
 
ebec02
 dist_noinst_DATA = README COPYING INSTALL fcoe-utils.spec etc/config
ebec02
 
ebec02
-BASH_COMPLETION_DIR=/etc/bash_completion.d/
ebec02
+BASH_COMPLETION_DIR=$(DESTDIR)/etc/bash_completion.d/
ebec02
 
ebec02
 install-data-hook:
ebec02
 	if [ ! -f ${DESTDIR}${fcoe_configdir}/config ] ; then \
ebec02
diff --git a/QUICKSTART b/QUICKSTART
ebec02
index 6fc82b3..c001bc1 100644
ebec02
--- a/QUICKSTART
ebec02
+++ b/QUICKSTART
ebec02
@@ -201,7 +201,10 @@ PROCESS
ebec02
 2) Bootstrap, configure, make and make install
ebec02
    # cd fcoe-utils
ebec02
    # ./bootstrap.sh
ebec02
+   Either execute the next line for System V init script install
ebec02
    # rpm --eval "%configure" | sh
ebec02
+   or the following line to install systemd unit scripts
ebec02
+   # rpm --eval "%configure --with-systemdsystemunitdir=/" | sh
ebec02
    # make
ebec02
    # make install
ebec02
 
ebec02
diff --git a/configure.ac b/configure.ac
ebec02
index 73c140f..107d039 100644
ebec02
--- a/configure.ac
ebec02
+++ b/configure.ac
ebec02
@@ -1,5 +1,4 @@
ebec02
 AC_INIT([fcoe-utils], [1.0.29], [fcoe-devel@open-fcoe.org])
ebec02
-AM_INIT_AUTOMAKE([foreign])
ebec02
 
ebec02
 m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
ebec02
 AM_INIT_AUTOMAKE([foreign])
ebec02
@@ -18,6 +17,14 @@ AC_SUBST([LLDPAD_CFLAGS])
ebec02
 PKG_CHECK_MODULES([LIBHBALINUX], [libhbalinux >= 1.0.13])
ebec02
 AC_SUBST([LIBHBALINUX_CFLAGS])
ebec02
 
ebec02
+PKG_PROG_PKG_CONFIG
ebec02
+AC_ARG_WITH([systemdsystemunitdir],
ebec02
+        AS_HELP_STRING([--with-systemdsystemunitdir=DIR],
ebec02
+			[Directory for systemd service files]), [],
ebec02
+			[with_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)])
ebec02
+AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])
ebec02
+AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$with_systemdsystemunitdir"])
ebec02
+
ebec02
 AC_CONFIG_FILES([Makefile fcoe-utils.spec include/fcoe_utils_version.h])
ebec02
 AC_OUTPUT
ebec02
 
ebec02
diff --git a/doc/fcoeadm.8 b/doc/fcoeadm.8
ebec02
index 11da6e3..2fefd70 100644
ebec02
--- a/doc/fcoeadm.8
ebec02
+++ b/doc/fcoeadm.8
ebec02
@@ -1,13 +1,13 @@
ebec02
 '\" t
ebec02
 .\"     Title: fcoeadm
ebec02
 .\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
ebec02
-.\" Generator: DocBook XSL Stylesheets v1.76.1 <http://docbook.sf.net/>
ebec02
-.\"      Date: 11/08/2012
ebec02
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
ebec02
+.\"      Date: 10/14/2013
ebec02
 .\"    Manual: Open-FCoE Tools
ebec02
 .\"    Source: Open-FCoE
ebec02
 .\"  Language: English
ebec02
 .\"
ebec02
-.TH "FCOEADM" "8" "11/08/2012" "Open\-FCoE" "Open\-FCoE Tools"
ebec02
+.TH "FCOEADM" "8" "10/14/2013" "Open\-FCoE" "Open\-FCoE Tools"
ebec02
 .\" -----------------------------------------------------------------
ebec02
 .\" * Define some portability stuff
ebec02
 .\" -----------------------------------------------------------------
ebec02
@@ -39,7 +39,7 @@ fcoeadm \- The Open\-FCoE Administration Tool
ebec02
 .sp
ebec02
 \fBfcoeadm\fR \-i|\-\-interface [\fIethX\fR]
ebec02
 .sp
ebec02
-\fBfcoeadm\fR \-f|\-\-fcfs [\fIethX\fR]
ebec02
+\fBfcoeadm\fR \-f|\-\-fcf [\fIethX\fR]
ebec02
 .sp
ebec02
 \fBfcoeadm\fR \-t|\-\-target [\fIethX\fR]
ebec02
 .sp
ebec02
@@ -91,7 +91,7 @@ Rescan for new targets and LUNs on the provided instance\&. This command will no
ebec02
 Show information about the FCoE instance on the specified network interface, or all FCoE instances if no network interface is specified\&.
ebec02
 .RE
ebec02
 .PP
ebec02
-\fB\-f\fR, \fB\-\-fcfs\fR [\fIethX\fR]
ebec02
+\fB\-f\fR, \fB\-\-fcf\fR [\fIethX\fR]
ebec02
 .RS 4
ebec02
 Show information about the discovered Fibre Channel Forwarders (FCFs) on the specified network interface, or all discovered FCFs if no network interface is specified\&.
ebec02
 .RE
ebec02
@@ -143,13 +143,9 @@ command\&.
ebec02
 .RE
ebec02
 .SH "INTERFACE NAMES"
ebec02
 .sp
ebec02
-The actual name for \fIethX\fR depends on the \fBAUTO_VLAN\fR setting in
ebec02
-the fcoemon interface configuration (/etc/fcoe/cfg-ethX, see \fBfcoemon\fR)\&.
ebec02
+The actual name for \fIethX\fR depends on the \fBAUTO_VLAN\fR setting in the fcoemon interface configuration (/etc/fcoe/cfg\-ethX, see \fBfcoemon\fR)\&.
ebec02
 .sp
ebec02
-If \fBAUTO_VLAN\fR is set to \fIyes\fR, the interface name \fIethX\fR
ebec02
-references the network device itself. If \fBAUTO_VLAN\fR is set to
ebec02
-\fIno\fR, the interface name \fIethX\fR references the VLAN device\&.
ebec02
-.RE
ebec02
+If \fBAUTO_VLAN\fR is set to \fIyes\fR, the interface name \fIethX\fR references the network device itself\&. If \fBAUTO_VLAN\fR is set to \fIno\fR, the interface name \fIethX\fR references the VLAN device\&.
ebec02
 .SH "EXAMPLES"
ebec02
 .sp
ebec02
 Creates an FCoE instance on eth2\&.101
ebec02
diff --git a/doc/fcoeadm.txt b/doc/fcoeadm.txt
ebec02
index 788625c..28ed482 100644
ebec02
--- a/doc/fcoeadm.txt
ebec02
+++ b/doc/fcoeadm.txt
ebec02
@@ -29,7 +29,7 @@ SYNOPSIS
ebec02
 
ebec02
 *fcoeadm* -i|--interface [_ethX_]
ebec02
 
ebec02
-*fcoeadm* -f|--fcfs [_ethX_]
ebec02
+*fcoeadm* -f|--fcf [_ethX_]
ebec02
 
ebec02
 *fcoeadm* -t|--target [_ethX_]
ebec02
 
ebec02
@@ -89,7 +89,7 @@ OPERATIONS
ebec02
 	Show information about the FCoE instance on the specified network
ebec02
 	interface, or all FCoE instances if no network interface is specified.
ebec02
 
ebec02
-*-f*, *--fcfs* [_ethX_]::
ebec02
+*-f*, *--fcf* [_ethX_]::
ebec02
 	Show information about the discovered Fibre Channel Forwarders (FCFs)
ebec02
 	on the specified network interface, or all discovered FCFs if no
ebec02
 	network interface is specified.
ebec02
diff --git a/doc/fcoemon.8 b/doc/fcoemon.8
ebec02
index e9a045b..020394e 100644
ebec02
--- a/doc/fcoemon.8
ebec02
+++ b/doc/fcoemon.8
ebec02
@@ -358,7 +358,7 @@ indicates whether a FIP responder should be activated on this device to support
ebec02
 Note that the attached Ethernet peer device (e\&.g\&. FCoE capable switch port) must have compatible settings For DCB and FCoE to function properly\&.
ebec02
 .SS "/etc/init\&.d/fcoe"
ebec02
 .sp
ebec02
-This is the \fBfcoe\fR system service script\&. This script is invoked by the init process or by the service command to start and stop the \fBfcoemon\fR\&.
ebec02
+This is the \fBfcoe\fR system service script\&. This script is invoked by the init process or by the service command to start and stop the \fBfcoemon\fR\&.  On systemd-enabled systems, \fBfcoemon\fR is controlled via the \fBfcoe.service\fR unit.
ebec02
 .SH "VLAN NAMING CONVENTIONS"
ebec02
 .sp
ebec02
 If a new VLAN device is created (see the description of the \fIAUTO_VLAN\fR setting above), it will have the name \fIdev\fR\&.\fIvlan\fR\-fcoe; where \fIdev\fR is the name of the Ethernet parent device and \fIvlan\fR is the discovered VLAN ID number\&.
ebec02
diff --git a/doc/fcoemon.txt b/doc/fcoemon.txt
ebec02
index ec15197..7ccf892 100644
ebec02
--- a/doc/fcoemon.txt
ebec02
+++ b/doc/fcoemon.txt
ebec02
@@ -56,7 +56,7 @@ OPTIONS
ebec02
 *-d*, *--debug*::
ebec02
 	Enable debugging messages.
ebec02
 *-l*, *--legacy*::
ebec02
-	Force fcoemon to use the legacy /sys/modlue/libfcoe/parameters/
ebec02
+	Force fcoemon to use the legacy /sys/module/libfcoe/parameters/
ebec02
 	interface. The default is to use the newer /sys/bus/fcoe/ interfaces
ebec02
 	if they are available.
ebec02
 *-s*, *--syslog*::
ebec02
@@ -214,6 +214,7 @@ must have compatible settings For DCB and FCoE to function properly.
ebec02
 ~~~~~~~~~~~~~~~~
ebec02
 This is the *fcoe* system service script. This script is invoked by the
ebec02
 init process or by the service command to start and stop the *fcoemon*.
ebec02
+On systemd-enabled systems, *fcoemon* is controlled via the *fcoe.service* unit.
ebec02
 
ebec02
 VLAN NAMING CONVENTIONS
ebec02
 -----------------------
ebec02
diff --git a/doc/fipvlan.8 b/doc/fipvlan.8
ebec02
index f81cb3a..1d2b707 100644
ebec02
--- a/doc/fipvlan.8
ebec02
+++ b/doc/fipvlan.8
ebec02
@@ -1,13 +1,13 @@
ebec02
 '\" t
ebec02
 .\"     Title: fipvlan
ebec02
 .\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
ebec02
-.\" Generator: DocBook XSL Stylesheets v1.76.1 <http://docbook.sf.net/>
ebec02
-.\"      Date: 03/18/2013
ebec02
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
ebec02
+.\"      Date: 12/02/2013
ebec02
 .\"    Manual: Open-FCoE Tools
ebec02
 .\"    Source: Open-FCoE
ebec02
 .\"  Language: English
ebec02
 .\"
ebec02
-.TH "FIPVLAN" "8" "03/18/2013" "Open\-FCoE" "Open\-FCoE Tools"
ebec02
+.TH "FIPVLAN" "8" "12/02/2013" "Open\-FCoE" "Open\-FCoE Tools"
ebec02
 .\" -----------------------------------------------------------------
ebec02
 .\" * Define some portability stuff
ebec02
 .\" -----------------------------------------------------------------
ebec02
@@ -29,9 +29,9 @@
ebec02
 fipvlan \- Fibre Channel over Ethernet VLAN Discovery
ebec02
 .SH "SYNOPSIS"
ebec02
 .sp
ebec02
-\fBfipvlan\fR [\-c|\-\-create] [\-s|\-\-start] [\-m|\-\-mode fabric|vn2vn] \fIinterfaces\fR
ebec02
+\fBfipvlan\fR [\-c|\-\-create] [\-d|\-\-debug] [\-s|\-\-start] [\-m|\-\-mode fabric|vn2vn] [\-u|\-\-link\-up] \fIinterfaces\fR
ebec02
 .sp
ebec02
-\fBfipvlan\fR \-a|\-\-auto [\-c|\-\-create] [\-d|\-\-debug] [\-s|\-\-start] [\-m|\-\-mode fabric|vn2vn] [\-l|\-\-link\-retry \fIcount\fR]
ebec02
+\fBfipvlan\fR \-a|\-\-auto [\-c|\-\-create] [\-d|\-\-debug] [\-s|\-\-start] [\-m|\-\-mode fabric|vn2vn] [\-l|\-\-link\-retry \fIcount\fR] [\-u|\-\-link\-up]
ebec02
 .sp
ebec02
 \fBfipvlan\fR \-h|\-\-help
ebec02
 .sp
ebec02
@@ -83,7 +83,12 @@ to VLAN interface names\&.
ebec02
 .RS 4
ebec02
 Retry check for link up to
ebec02
 \fIcount\fR
ebec02
-times\&. The link state is checked every 500 ms\&. The default number of retries is 20\&.
ebec02
+times\&. The link state is checked every 1000 ms\&. The default number of retries is 20\&.
ebec02
+.RE
ebec02
+.PP
ebec02
+\fB\-u\fR, \fB\-\-link\-up\fR
ebec02
+.RS 4
ebec02
+Leave link up if a FIP response has been received\&.
ebec02
 .RE
ebec02
 .PP
ebec02
 \fB\-h\fR, \fB\-\-help\fR
ebec02
diff --git a/doc/fipvlan.txt b/doc/fipvlan.txt
ebec02
index 9699197..5ba0324 100644
ebec02
--- a/doc/fipvlan.txt
ebec02
+++ b/doc/fipvlan.txt
ebec02
@@ -19,10 +19,12 @@ fipvlan - Fibre Channel over Ethernet VLAN Discovery
ebec02
 
ebec02
 SYNOPSIS
ebec02
 --------
ebec02
-*fipvlan* [-c|--create] [-s|--start] [-m|--mode fabric|vn2vn] _interfaces_
ebec02
+*fipvlan* [-c|--create] [-d|--debug] [-s|--start]
ebec02
+ [-m|--mode fabric|vn2vn] [-u|--link-up] _interfaces_
ebec02
 
ebec02
 *fipvlan* -a|--auto [-c|--create] [-d|--debug]
ebec02
  [-s|--start] [-m|--mode fabric|vn2vn] [-l|--link-retry _count_]
ebec02
+ [-u|--link-up]
ebec02
 
ebec02
 *fipvlan* -h|--help
ebec02
 
ebec02
@@ -73,7 +75,10 @@ OPTIONS
ebec02
 
ebec02
 *-l*, *--link-retry* _count_::
ebec02
 	Retry check for link up to _count_ times. The link state is
ebec02
-	checked every 500 ms. The default number of retries is 20.
ebec02
+	checked every 1000 ms. The default number of retries is 20.
ebec02
+
ebec02
+*-u*, *--link-up*::
ebec02
+	Leave link up if a FIP response has been received.
ebec02
 
ebec02
 *-h*, *--help*::
ebec02
 	Display a help message with basic usage instructions
ebec02
diff --git a/etc/systemd/fcoe.service b/etc/systemd/fcoe.service
ebec02
new file mode 100644
ebec02
index 0000000..5e5c8a2
ebec02
--- /dev/null
ebec02
+++ b/etc/systemd/fcoe.service
ebec02
@@ -0,0 +1,14 @@
ebec02
+[Unit]
ebec02
+Description=Open-FCoE initiator daemon
ebec02
+After=syslog.target network.target
ebec02
+
ebec02
+[Service]
ebec02
+Type=simple
ebec02
+EnvironmentFile=/etc/sysconfig/fcoe
ebec02
+ExecStartPre=/sbin/modprobe -qa $SUPPORTED_DRIVERS
ebec02
+ExecStart=/usr/sbin/fcoemon $FCOEMON_OPTS
ebec02
+
ebec02
+[Install]
ebec02
+WantedBy=multi-user.target
ebec02
+Also=lldpad.socket
ebec02
+Also=fcoemon.socket
ebec02
diff --git a/etc/systemd/fcoemon.socket b/etc/systemd/fcoemon.socket
ebec02
new file mode 100644
ebec02
index 0000000..4de8715
ebec02
--- /dev/null
ebec02
+++ b/etc/systemd/fcoemon.socket
ebec02
@@ -0,0 +1,6 @@
ebec02
+[Socket]
ebec02
+ListenDatagram=@/com/intel/fcoemon
ebec02
+PassCredentials=true
ebec02
+
ebec02
+[Install]
ebec02
+WantedBy=sockets.target
ebec02
diff --git a/fcnsq.c b/fcnsq.c
ebec02
index 7b45a32..1597cd5 100644
ebec02
--- a/fcnsq.c
ebec02
+++ b/fcnsq.c
ebec02
@@ -24,6 +24,7 @@
ebec02
 #include <stdarg.h>
ebec02
 #include <stdbool.h>
ebec02
 #include <unistd.h>
ebec02
+#include <inttypes.h>
ebec02
 #include <string.h>
ebec02
 #include <errno.h>
ebec02
 #include <fcntl.h>
ebec02
@@ -228,7 +229,7 @@ static int gpn_id(int bsg, u32 fcid)
ebec02
 	rjt = gn_id(bsg, fcid, FC_NS_GPN_ID, &wwpn);
ebec02
 	if (rjt)
ebec02
 		goto fail;
ebec02
-	print_result("Port Name", "%16.16llx\n", wwpn);
ebec02
+	print_result("Port Name", "%16.16jx\n", (uintmax_t)wwpn);
ebec02
 	return 0;
ebec02
 fail:
ebec02
 	if (rjt == (u16) ~0)
ebec02
@@ -249,7 +250,7 @@ static int gnn_id(int bsg, u32 fcid)
ebec02
 	rjt = gn_id(bsg, fcid, FC_NS_GNN_ID, &wwnn);
ebec02
 	if (rjt)
ebec02
 		goto fail;
ebec02
-	print_result("Node Name", "%16.16llx\n", wwnn);
ebec02
+	print_result("Node Name", "%16.16jx\n", (uintmax_t)wwnn);
ebec02
 	return 0;
ebec02
 fail:
ebec02
 	if (rjt == (u16) ~0)
ebec02
@@ -365,7 +366,7 @@ static void help(int status)
ebec02
 		"  --gspn <port id>\n"
ebec02
 		"  --gsnn <world wide node name>\n"
ebec02
 		"Options:\n"
ebec02
-		"  --quiet	print minimal results on success, and no error messages\n"
ebec02
+		"  --quiet|-q	print minimal results on success, and no error messages\n"
ebec02
 		"\n"
ebec02
 		"Port IDs and World Wide Names must be specified in hexadecimal.\n"
ebec02
 		);
ebec02
@@ -376,11 +377,12 @@ int main(int argc, char *argv[])
ebec02
 {
ebec02
 	char *bsg;
ebec02
 	int bsg_dev;
ebec02
-	u32 port_id;
ebec02
-	u64 wwnn;
ebec02
+	u32 port_id = 0;
ebec02
+	u64 wwnn = 0;
ebec02
 	int rc = 0;
ebec02
 	enum commands cmd = 0;
ebec02
 	char c;
ebec02
+	uintmax_t wwnn_tmp = 0;
ebec02
 
ebec02
 	while(1) {
ebec02
 		c = getopt_long_only(argc, argv, "", options, NULL);
ebec02
@@ -399,13 +401,17 @@ int main(int argc, char *argv[])
ebec02
 			if (cmd)
ebec02
 				help(-1);
ebec02
 			cmd = c;
ebec02
-			sscanf(optarg, "%x", &port_id);
ebec02
+			if (sscanf(optarg, "%x", &port_id) != 1)
ebec02
+				help(-1);
ebec02
 			break;
ebec02
 		case GSNN_NN:
ebec02
 			if (cmd)
ebec02
 				help(-1);
ebec02
 			cmd = c;
ebec02
-			sscanf(optarg, "%llx", &wwnn);
ebec02
+			if (sscanf(optarg, "%jx", &wwnn_tmp) == 1)
ebec02
+				wwnn = (u64)wwnn_tmp;
ebec02
+			else
ebec02
+				help(-1);
ebec02
 			break;
ebec02
 		}
ebec02
 	}
ebec02
diff --git a/fcoeadm_display.c b/fcoeadm_display.c
ebec02
index 287e370..9b96170 100644
ebec02
--- a/fcoeadm_display.c
ebec02
+++ b/fcoeadm_display.c
ebec02
@@ -110,7 +110,13 @@ struct sa_nameval port_speeds[] = {
ebec02
 	{ "Unknown",        HBA_PORTSPEED_UNKNOWN },
ebec02
 	{ "1 Gbit",         HBA_PORTSPEED_1GBIT },
ebec02
 	{ "2 Gbit",         HBA_PORTSPEED_2GBIT },
ebec02
+	{ "4 Gbit",         HBA_PORTSPEED_4GBIT },
ebec02
 	{ "10 Gbit",        HBA_PORTSPEED_10GBIT },
ebec02
+	{ "8 Gbit",         HBA_PORTSPEED_8GBIT },
ebec02
+	{ "16 Gbit",        HBA_PORTSPEED_16GBIT },
ebec02
+	{ "32 Gbit",        HBA_PORTSPEED_32GBIT },
ebec02
+	{ "20 Gbit",        HBA_PORTSPEED_20GBIT },
ebec02
+	{ "40 Gbit",        HBA_PORTSPEED_40GBIT },
ebec02
 	{ "Not Negotiated", HBA_PORTSPEED_NOT_NEGOTIATED },
ebec02
 	{ NULL, 0 }
ebec02
 };
ebec02
@@ -1417,8 +1423,8 @@ static void print_fcoe_fcf_device(void *ep, UNUSED void *arg)
ebec02
 	if (!buf)
ebec02
 		buf = temp;
ebec02
 	printf("        Connection Mode:  %s\n", buf);
ebec02
-	printf("        Fabric Name:      0x%016lx\n", fcf->fabric_name);
ebec02
-	printf("        Switch Name       0x%016lx\n", fcf->switch_name);
ebec02
+	printf("        Fabric Name:      0x%016" PRIx64 "\n", fcf->fabric_name);
ebec02
+	printf("        Switch Name       0x%016" PRIx64 "\n", fcf->switch_name);
ebec02
 	mac2str(fcf->mac, mac, MAX_STR_LEN);
ebec02
 	printf("        MAC Address:      %s\n", mac);
ebec02
 	printf("        FCF Priority:     %u\n", fcf->priority);
ebec02
diff --git a/fcoemon.c b/fcoemon.c
ebec02
index a5babfa..b3120bc 100644
ebec02
--- a/fcoemon.c
ebec02
+++ b/fcoemon.c
ebec02
@@ -1357,12 +1357,8 @@ ieee_state_set(struct fcm_netif *ff, enum ieee_state new_state)
ebec02
 				getstr(&ieee_states, new_state));
ebec02
 	}
ebec02
 
ebec02
-	if (new_state == IEEE_GET_STATE) {
ebec02
-		ff->ieee_state = new_state;
ebec02
+	if (new_state == IEEE_GET_STATE)
ebec02
 		clear_ieee_info(ff);
ebec02
-		ieee_get_req(ff);
ebec02
-		return;
ebec02
-	}
ebec02
 
ebec02
 	ff->ieee_state = new_state;
ebec02
 	ff->ieee_resp_pending = 0;
ebec02
@@ -2637,7 +2633,7 @@ static void fcm_dcbd_get_oper(struct fcm_netif *ff, char *resp, char *cp)
ebec02
 
ebec02
 	if (ep) {
ebec02
 		FCM_LOG_DEV(ff, "Invalid get oper response "
ebec02
-			    "parse error byte %ld, resp %s", ep - cp, cp);
ebec02
+			    "parse error byte %td, resp %s", ep - cp, cp);
ebec02
 		fcm_dcbd_state_set(ff, FCD_ERROR);
ebec02
 	} else {
ebec02
 		if (val && fcoe_config.debug)
ebec02
@@ -3035,6 +3031,50 @@ static void fcm_fcoe_action(struct fcoe_port *p)
ebec02
 
ebec02
 /*
ebec02
  * Called for all ports.  For FCoE ports and candidates,
ebec02
+ * get IEEE DCBX information and set the next action.
ebec02
+ */
ebec02
+static void fcm_netif_ieee_advance(struct fcm_netif *ff)
ebec02
+{
ebec02
+	enum fcp_action action;
ebec02
+
ebec02
+	ASSERT(ff);
ebec02
+	ASSERT(fcm_clif);
ebec02
+
ebec02
+	if (fcm_clif->cl_busy)
ebec02
+		return;
ebec02
+
ebec02
+	if (ff->ieee_resp_pending)
ebec02
+		return;
ebec02
+
ebec02
+	switch (ff->ieee_state) {
ebec02
+	case IEEE_INIT:
ebec02
+		break;
ebec02
+	case IEEE_GET_STATE:
ebec02
+		ieee_get_req(ff);
ebec02
+		break;
ebec02
+	case IEEE_DONE:
ebec02
+		action = validate_ieee_info(ff);
ebec02
+		switch (action) {
ebec02
+		case FCP_DESTROY_IF:
ebec02
+		case FCP_ENABLE_IF:
ebec02
+		case FCP_ACTIVATE_IF:
ebec02
+			fcp_action_set(ff->ifname, action);
ebec02
+			break;
ebec02
+		case FCP_DISABLE_IF:
ebec02
+		case FCP_ERROR:
ebec02
+			fcp_action_set(ff->ifname, FCP_DISABLE_IF);
ebec02
+			break;
ebec02
+		case FCP_WAIT:
ebec02
+		default:
ebec02
+			break;
ebec02
+		}
ebec02
+	default:
ebec02
+		break;
ebec02
+	}
ebec02
+}
ebec02
+
ebec02
+/*
ebec02
+ * Called for all ports.  For FCoE ports and candidates,
ebec02
  * get information and send to dcbd.
ebec02
  */
ebec02
 static void fcm_netif_advance(struct fcm_netif *ff)
ebec02
@@ -3161,8 +3201,10 @@ static void fcm_handle_changes(void)
ebec02
 	/*
ebec02
 	 * Perform pending actions (dcbd queries) on network interfaces.
ebec02
 	 */
ebec02
-	TAILQ_FOREACH(ff, &fcm_netif_head, ff_list)
ebec02
+	TAILQ_FOREACH(ff, &fcm_netif_head, ff_list) {
ebec02
 		fcm_netif_advance(ff);
ebec02
+		fcm_netif_ieee_advance(ff);
ebec02
+	}
ebec02
 
ebec02
 	/*
ebec02
 	 * Perform actions on FCoE ports
ebec02
@@ -3546,12 +3588,54 @@ err:
ebec02
 	sendto(snum, rbuf, MSG_RBUF, 0, (struct sockaddr *)&from, fromlen);
ebec02
 }
ebec02
 
ebec02
+static int fcm_systemd_socket(void)
ebec02
+{
ebec02
+	char *env, *ptr;
ebec02
+	unsigned int p, l;
ebec02
+
ebec02
+	env = getenv("LISTEN_PID");
ebec02
+	if (!env)
ebec02
+		return -1;
ebec02
+
ebec02
+	p = strtoul(env, &ptr, 10);
ebec02
+	if (ptr && ptr == env) {
ebec02
+		FCM_LOG_DBG("Invalid value '%s' for LISTEN_PID\n", env);
ebec02
+		return -1;
ebec02
+	}
ebec02
+	if ((pid_t)p != getpid()) {
ebec02
+		FCM_LOG_DBG("Invalid PID '%d' from LISTEN_PID\n", p);
ebec02
+		return -1;
ebec02
+	}
ebec02
+	env = getenv("LISTEN_FDS");
ebec02
+	if (!env) {
ebec02
+		FCM_LOG_DBG("LISTEN_FDS is not set\n");
ebec02
+		return -1;
ebec02
+	}
ebec02
+	l = strtoul(env, &ptr, 10);
ebec02
+	if (ptr && ptr == env) {
ebec02
+		FCM_LOG_DBG("Invalid value '%s' for LISTEN_FDS\n", env);
ebec02
+		return -1;
ebec02
+	}
ebec02
+	if (l != 1) {
ebec02
+		FCM_LOG_DBG("LISTEN_FDS specified %d fds\n", l);
ebec02
+		return -1;
ebec02
+	}
ebec02
+	/* systemd returns fds with an offset of '3' */
ebec02
+	return 3;
ebec02
+}
ebec02
+
ebec02
 static int fcm_srv_create(struct fcm_srv_info *srv_info)
ebec02
 {
ebec02
 	socklen_t addrlen;
ebec02
 	struct sockaddr_un addr;
ebec02
 	int rc = 0;
ebec02
 
ebec02
+	srv_info->srv_sock = fcm_systemd_socket();
ebec02
+	if (srv_info->srv_sock > 0) {
ebec02
+		FCM_LOG_DBG("Using systemd socket\n");
ebec02
+		goto out_done;
ebec02
+	}
ebec02
+
ebec02
 	srv_info->srv_sock = socket(AF_LOCAL, SOCK_DGRAM, 0);
ebec02
 	if (srv_info->srv_sock < 0) {
ebec02
 		FCM_LOG_ERR(errno, "Failed to create socket\n");
ebec02
@@ -3570,7 +3654,7 @@ static int fcm_srv_create(struct fcm_srv_info *srv_info)
ebec02
 		rc = errno;
ebec02
 		goto err_close;
ebec02
 	}
ebec02
-
ebec02
+out_done:
ebec02
 	sa_select_add_fd(srv_info->srv_sock, fcm_srv_receive,
ebec02
 			 NULL, NULL, srv_info);
ebec02
 
ebec02
diff --git a/fcping.c b/fcping.c
ebec02
index c6f74a6..399b778 100644
ebec02
--- a/fcping.c
ebec02
+++ b/fcping.c
ebec02
@@ -25,6 +25,7 @@
ebec02
 #include <stddef.h>
ebec02
 #include <stdarg.h>
ebec02
 #include <unistd.h>
ebec02
+#include <inttypes.h>
ebec02
 #include <errno.h>
ebec02
 #include <string.h>
ebec02
 #include <time.h>
ebec02
@@ -810,17 +811,17 @@ static void fp_check_data_len(void)
ebec02
 	printf("Maximum ECHO data allowed by the Fabric (0x%06x) : %d bytes.\n"
ebec02
 	       "Maximum ECHO data allowed by the Source (0x%06x) : %d bytes.\n"
ebec02
 	       "Maximum ECHO data allowed by the Target (0x%06x) : %d bytes.\n"
ebec02
-	       "Maximum ECHO data requested from user input (-s) : %lu "
ebec02
+	       "Maximum ECHO data requested from user input (-s) : %" PRIu32 " "
ebec02
 	       "(default %d) bytes.\n",
ebec02
 	       FC_WKA_FABRIC_CONTROLLER, flen, sid, slen, fp_did, dlen,
ebec02
-	       fp_len - FP_LEN_ECHO, FP_LEN_DEF);
ebec02
+	       (uint32_t)(fp_len - FP_LEN_ECHO), FP_LEN_DEF);
ebec02
 
ebec02
 	/* fp_len is the total payload, including 4 bytes for ECHO command */
ebec02
 	fp_len = MIN(fp_len, plen + FP_LEN_ECHO);
ebec02
-	printf("Actual FC ELS ECHO data size used : %lu bytes.\n"
ebec02
+	printf("Actual FC ELS ECHO data size used : %" PRIu32 " bytes.\n"
ebec02
 	       "Actual FC ELS ECHO payload size used : %d bytes "
ebec02
-	       "(including %ld bytes ECHO command).\n",
ebec02
-	       fp_len - FP_LEN_ECHO, fp_len, FP_LEN_ECHO);
ebec02
+	       "(including %zu bytes ECHO command).\n",
ebec02
+	       (uint32_t)(fp_len - FP_LEN_ECHO), fp_len, FP_LEN_ECHO);
ebec02
 }
ebec02
 
ebec02
 /*
ebec02
diff --git a/fipvlan.c b/fipvlan.c
ebec02
index 6f8cf39..cc71412 100644
ebec02
--- a/fipvlan.c
ebec02
+++ b/fipvlan.c
ebec02
@@ -67,6 +67,7 @@ struct {
ebec02
 	bool start;
ebec02
 	bool vn2vn;
ebec02
 	bool debug;
ebec02
+	bool link_up;
ebec02
 	int link_retry;
ebec02
 	char suffix[256];
ebec02
 } config = {
ebec02
@@ -76,6 +77,7 @@ struct {
ebec02
 	.create = false,
ebec02
 	.vn2vn = false,
ebec02
 	.debug = false,
ebec02
+	.link_up = false,
ebec02
 	.link_retry = 20,
ebec02
 	.suffix = "",
ebec02
 };
ebec02
@@ -139,6 +141,7 @@ struct iff {
ebec02
 	bool req_sent;
ebec02
 	bool resp_recv;
ebec02
 	bool fip_ready;
ebec02
+	bool fcoe_started;
ebec02
 	TAILQ_ENTRY(iff) list_node;
ebec02
 	struct iff_list_head vlans;
ebec02
 };
ebec02
@@ -157,6 +160,8 @@ struct fcf {
ebec02
 struct fcf_list_head fcfs = TAILQ_HEAD_INITIALIZER(fcfs);
ebec02
 static struct fcf_list_head vn2vns = TAILQ_HEAD_INITIALIZER(vn2vns);
ebec02
 
ebec02
+static int create_and_start_vlan(struct fcf *fcf, bool vn2vn);
ebec02
+
ebec02
 static struct fcf *lookup_fcf(struct fcf_list_head *head, int ifindex,
ebec02
 			      uint16_t vlan, unsigned char *mac)
ebec02
 {
ebec02
@@ -316,6 +321,9 @@ static int fip_recv_vlan_note(struct fiphdr *fh, int ifindex, bool vn2vn)
ebec02
 		fcf->vlan = vlan;
ebec02
 		memcpy(fcf->mac_addr, tlvs.mac->mac_addr, ETHER_ADDR_LEN);
ebec02
 		TAILQ_INSERT_TAIL(head, fcf, list_node);
ebec02
+		if (!config.create)
ebec02
+			continue;
ebec02
+		create_and_start_vlan(fcf, vn2vn);
ebec02
 	}
ebec02
 
ebec02
 	return 0;
ebec02
@@ -362,8 +370,14 @@ static void rtnl_recv_newlink(struct nlmsghdr *nh)
ebec02
 	struct rtattr *linkinfo[__IFLA_INFO_MAX];
ebec02
 	struct rtattr *vlan[__IFLA_VLAN_MAX];
ebec02
 	struct iff *iff, *real_dev;
ebec02
+	struct fcf_list_head *head;
ebec02
 	bool running;
ebec02
 
ebec02
+	if (config.vn2vn)
ebec02
+		head = &vn2vns;
ebec02
+	else
ebec02
+		head = &fcf;;
ebec02
+
ebec02
 	FIP_LOG_DBG("RTM_NEWLINK: ifindex %d, type %d, flags %x",
ebec02
 		    ifm->ifi_index, ifm->ifi_type, ifm->ifi_flags);
ebec02
 
ebec02
@@ -378,12 +392,38 @@ static void rtnl_recv_newlink(struct nlmsghdr *nh)
ebec02
 	running = !!(ifm->ifi_flags & (IFF_RUNNING | IFF_SLAVE));
ebec02
 	iff = lookup_iff(ifm->ifi_index, NULL);
ebec02
 	if (iff) {
ebec02
+		int ifindex;
ebec02
+
ebec02
 		/* already tracking, update operstate and return */
ebec02
 		iff->running = running;
ebec02
-		if (iff->running)
ebec02
-			pfd_add(iff->ps);
ebec02
-		else
ebec02
+		if (!iff->running) {
ebec02
 			pfd_remove(iff->ps);
ebec02
+			return;
ebec02
+		}
ebec02
+		pfd_add(iff->ps);
ebec02
+		if (!config.start)
ebec02
+			return;
ebec02
+
ebec02
+		FIP_LOG_DBG("Checking for FCoE on %sif %d",
ebec02
+			    iff->is_vlan ? "VLAN " : "", iff->ifindex);
ebec02
+		if (iff->is_vlan) {
ebec02
+			real_dev = find_vlan_real_dev(iff);
ebec02
+			if (!real_dev) {
ebec02
+				FIP_LOG_ERR(ENODEV, "VLAN %d without a parent",
ebec02
+					    iff->ifindex);
ebec02
+				return;
ebec02
+			}
ebec02
+			ifindex = real_dev->ifindex;
ebec02
+		} else
ebec02
+			ifindex = iff->ifindex;
ebec02
+
ebec02
+		if (!iff->fcoe_started &&
ebec02
+		    lookup_fcf(head, ifindex, iff->vid, NULL)) {
ebec02
+			printf("Starting FCoE on interface %s\n",
ebec02
+			       iff->ifname);
ebec02
+			fcoe_instance_start(iff->ifname);
ebec02
+			iff->fcoe_started = true;
ebec02
+		}
ebec02
 		return;
ebec02
 	}
ebec02
 
ebec02
@@ -407,6 +447,19 @@ static void rtnl_recv_newlink(struct nlmsghdr *nh)
ebec02
 	memcpy(iff->mac_addr, RTA_DATA(ifla[IFLA_ADDRESS]), ETHER_ADDR_LEN);
ebec02
 	strncpy(iff->ifname, RTA_DATA(ifla[IFLA_IFNAME]), IFNAMSIZ);
ebec02
 
ebec02
+	if (!config.automode) {
ebec02
+		int i, iff_selected = 0;
ebec02
+
ebec02
+		for (i = 0; i < config.namec; i++) {
ebec02
+			if (!strcmp(iff->ifname, config.namev[i]))
ebec02
+				iff_selected = 1;
ebec02
+		}
ebec02
+		if (!iff_selected) {
ebec02
+			FIP_LOG_DBG("ignoring if %s\n", iff->ifname);
ebec02
+			free(iff);
ebec02
+			return;
ebec02
+		}
ebec02
+	}
ebec02
 	if (ifla[IFLA_LINKINFO]) {
ebec02
 		parse_linkinfo(linkinfo, ifla[IFLA_LINKINFO]);
ebec02
 		/* Track VLAN devices separately */
ebec02
@@ -416,11 +469,16 @@ static void rtnl_recv_newlink(struct nlmsghdr *nh)
ebec02
 			parse_vlaninfo(vlan, linkinfo[IFLA_INFO_DATA]);
ebec02
 			iff->vid = *(int *)RTA_DATA(vlan[IFLA_VLAN_ID]);
ebec02
 			real_dev = find_vlan_real_dev(iff);
ebec02
-			if (real_dev)
ebec02
-				TAILQ_INSERT_TAIL(&real_dev->vlans,
ebec02
-						  iff, list_node);
ebec02
-			else
ebec02
+			if (!real_dev) {
ebec02
 				free(iff);
ebec02
+				return;
ebec02
+			}
ebec02
+			TAILQ_INSERT_TAIL(&real_dev->vlans, iff, list_node);
ebec02
+			if (!iff->running) {
ebec02
+				FIP_LOG_DBG("vlan if %d not running, "
ebec02
+					    "starting", iff->ifindex);
ebec02
+				rtnl_set_iff_up(iff->ifindex, NULL);
ebec02
+			}
ebec02
 			return;
ebec02
 		}
ebec02
 		/* ignore bonding interfaces */
ebec02
@@ -435,7 +493,7 @@ static void rtnl_recv_newlink(struct nlmsghdr *nh)
ebec02
 
ebec02
 /* command line arguments */
ebec02
 
ebec02
-#define GETOPT_STR "acdf:l:m:shv"
ebec02
+#define GETOPT_STR "acdf:l:m:suhv"
ebec02
 
ebec02
 static const struct option long_options[] = {
ebec02
 	{ "auto", no_argument, NULL, 'a' },
ebec02
@@ -445,6 +503,7 @@ static const struct option long_options[] = {
ebec02
 	{ "suffix", required_argument, NULL, 'f' },
ebec02
 	{ "link-retry", required_argument, NULL, 'l' },
ebec02
 	{ "mode", required_argument, NULL, 'm' },
ebec02
+	{ "link-up", required_argument, NULL, 'u' },
ebec02
 	{ "help", no_argument, NULL, 'h' },
ebec02
 	{ "version", no_argument, NULL, 'v' },
ebec02
 	{ NULL, 0, NULL, 0 }
ebec02
@@ -462,6 +521,7 @@ static void help(int status)
ebec02
 		"  -f, --suffix		Append the suffix to VLAN interface name\n"
ebec02
 		"  -l, --link-retry     Number of retries for link up\n"
ebec02
 		"  -m, --mode           Link mode, either fabric or vn2vn\n"
ebec02
+		"  -u, --link-up        Leave link up after FIP response\n"
ebec02
 		"  -h, --help           Display this help and exit\n"
ebec02
 		"  -v, --version        Display version information and exit\n",
ebec02
 		exe);
ebec02
@@ -471,7 +531,7 @@ static void help(int status)
ebec02
 
ebec02
 static void parse_cmdline(int argc, char **argv)
ebec02
 {
ebec02
-	char c;
ebec02
+	signed char c;
ebec02
 
ebec02
 	while (1) {
ebec02
 		c = getopt_long(argc, argv, GETOPT_STR, long_options, NULL);
ebec02
@@ -508,6 +568,9 @@ static void parse_cmdline(int argc, char **argv)
ebec02
 				exit(1);
ebec02
 			}
ebec02
 			break;
ebec02
+		case 'u':
ebec02
+			config.link_up = true;
ebec02
+			break;
ebec02
 		case 'h':
ebec02
 			help(0);
ebec02
 			break;
ebec02
@@ -539,59 +602,60 @@ static int rtnl_listener_handler(struct nlmsghdr *nh, UNUSED void *arg)
ebec02
 	return -1;
ebec02
 }
ebec02
 
ebec02
-static void
ebec02
-create_missing_vlans_list(struct fcf_list_head *list, const char *label)
ebec02
+static int
ebec02
+create_and_start_vlan(struct fcf *fcf, bool vn2vn)
ebec02
 {
ebec02
-	struct fcf *fcf;
ebec02
 	struct iff *real_dev, *vlan;
ebec02
 	char vlan_name[IFNAMSIZ];
ebec02
 	int rc;
ebec02
 
ebec02
-	if (!config.create)
ebec02
-		return;
ebec02
-
ebec02
-	TAILQ_FOREACH(fcf, list, list_node) {
ebec02
-		real_dev = lookup_iff(fcf->ifindex, NULL);
ebec02
-		if (!real_dev) {
ebec02
-			FIP_LOG_ERR(ENODEV,
ebec02
-				    "lost device %d with discovered %s?\n",
ebec02
-				    fcf->ifindex, label);
ebec02
-			continue;
ebec02
-		}
ebec02
-		if (!fcf->vlan) {
ebec02
-			/*
ebec02
-			 * If the vlan notification has VLAN id 0,
ebec02
-			 * skip creating vlan interface, and FCoE is
ebec02
-			 * started on the physical interface itself.
ebec02
-			 */
ebec02
-			FIP_LOG_DBG("VLAN id is 0 for %s\n", real_dev->ifname);
ebec02
-			continue;
ebec02
-		}
ebec02
+	real_dev = lookup_iff(fcf->ifindex, NULL);
ebec02
+	if (!real_dev) {
ebec02
+		FIP_LOG_ERR(ENODEV,
ebec02
+			    "lost device %d with discovered %s?\n",
ebec02
+			    fcf->ifindex, vn2vn ? "VN2VN" : "FCF");
ebec02
+		return -ENXIO;
ebec02
+	}
ebec02
+	if (!fcf->vlan) {
ebec02
+		/*
ebec02
+		 * If the vlan notification has VLAN id 0,
ebec02
+		 * skip creating vlan interface, and FCoE is
ebec02
+		 * started on the physical interface itself.
ebec02
+		 */
ebec02
+		FIP_LOG_DBG("VLAN id is 0 for %s\n", real_dev->ifname);
ebec02
+		vlan = real_dev;
ebec02
+	} else {
ebec02
 		vlan = lookup_vlan(fcf->ifindex, fcf->vlan);
ebec02
 		if (vlan) {
ebec02
 			FIP_LOG_DBG("VLAN %s.%d already exists as %s\n",
ebec02
 				    real_dev->ifname, fcf->vlan, vlan->ifname);
ebec02
-			continue;
ebec02
+			return 0;
ebec02
 		}
ebec02
 		snprintf(vlan_name, IFNAMSIZ, "%s.%d%s",
ebec02
 			 real_dev->ifname, fcf->vlan, config.suffix);
ebec02
 		rc = vlan_create(fcf->ifindex, fcf->vlan, vlan_name);
ebec02
-		if (rc < 0)
ebec02
+		if (rc < 0) {
ebec02
 			printf("Failed to create VLAN device %s\n\t%s\n",
ebec02
 			       vlan_name, strerror(-rc));
ebec02
-		else
ebec02
-			printf("Created VLAN device %s\n", vlan_name);
ebec02
-		rtnl_set_iff_up(0, vlan_name);
ebec02
+			return rc;
ebec02
+		}
ebec02
+		printf("Created VLAN device %s\n", vlan_name);
ebec02
 	}
ebec02
-	printf("\n");
ebec02
-}
ebec02
+	if (!config.start)
ebec02
+		return rc;
ebec02
 
ebec02
-static void create_missing_vlans(void)
ebec02
-{
ebec02
-	if (!TAILQ_EMPTY(&fcfs))
ebec02
-		create_missing_vlans_list(&fcfs, "FCF");
ebec02
-	if (!TAILQ_EMPTY(&vn2vns))
ebec02
-		create_missing_vlans_list(&vn2vns, "VN2VN");
ebec02
+	if (!vlan->running) {
ebec02
+		FIP_LOG_DBG("%s if %d not running, starting",
ebec02
+			    vlan == real_dev ? "real" : "vlan",
ebec02
+			    vlan->ifindex);
ebec02
+		rtnl_set_iff_up(vlan->ifindex, NULL);
ebec02
+	} else if (!vlan->fcoe_started) {
ebec02
+		printf("Starting FCoE on interface %s\n",
ebec02
+		       vlan->ifname);
ebec02
+		fcoe_instance_start(vlan->ifname);
ebec02
+		vlan->fcoe_started = true;
ebec02
+	}
ebec02
+	return rc;
ebec02
 }
ebec02
 
ebec02
 static int fcoe_mod_instance_start(const char *ifname)
ebec02
@@ -666,34 +730,6 @@ static void determine_libfcoe_interface(void)
ebec02
 	}
ebec02
 }
ebec02
 
ebec02
-static void start_fcoe(void)
ebec02
-{
ebec02
-	struct fcf_list_head *head;
ebec02
-	struct fcf *fcf;
ebec02
-	struct iff *iff;
ebec02
-
ebec02
-	if (config.vn2vn)
ebec02
-		head = &vn2vns;
ebec02
-	else
ebec02
-		head = &fcf;;
ebec02
-
ebec02
-	TAILQ_FOREACH(fcf, head, list_node) {
ebec02
-		if (fcf->vlan)
ebec02
-			iff = lookup_vlan(fcf->ifindex, fcf->vlan);
ebec02
-		else
ebec02
-			iff = lookup_iff(fcf->ifindex, NULL);
ebec02
-		if (!iff) {
ebec02
-			FIP_LOG_ERR(ENODEV,
ebec02
-				    "Cannot start FCoE on VLAN %d, ifindex %d, "
ebec02
-				    "because the VLAN device does not exist",
ebec02
-				    fcf->vlan, fcf->ifindex);
ebec02
-			continue;
ebec02
-		}
ebec02
-		printf("Starting FCoE on interface %s\n", iff->ifname);
ebec02
-		fcoe_instance_start(iff->ifname);
ebec02
-	}
ebec02
-}
ebec02
-
ebec02
 static void print_list(struct fcf_list_head *list, const char *label)
ebec02
 {
ebec02
 	struct iff *iff;
ebec02
@@ -749,9 +785,15 @@ static void recv_loop(int timeout)
ebec02
 			rtnl_recv(pfd[0].fd, rtnl_listener_handler, NULL);
ebec02
 		/* everything else should be FIP packet sockets */
ebec02
 		for (i = 1; i < pfd_len; i++) {
ebec02
-			if (pfd[i].revents & POLLIN)
ebec02
-				fip_recv(pfd[i].fd, fip_vlan_handler, NULL);
ebec02
+			if (pfd[i].revents & POLLIN) {
ebec02
+				rc = fip_recv(pfd[i].fd, fip_vlan_handler,
ebec02
+					      NULL);
ebec02
+				if (rc < 0)
ebec02
+					break;
ebec02
+			}
ebec02
 		}
ebec02
+		if (i < pfd_len)
ebec02
+			break;
ebec02
 	}
ebec02
 }
ebec02
 
ebec02
@@ -763,7 +805,7 @@ static void find_interfaces(int ns)
ebec02
 
ebec02
 static int probe_fip_interface(struct iff *iff)
ebec02
 {
ebec02
-	int origdev = 1;
ebec02
+	int origdev = 1, rc;
ebec02
 
ebec02
 	if (iff->resp_recv)
ebec02
 		return 0;
ebec02
@@ -785,6 +827,10 @@ static int probe_fip_interface(struct iff *iff)
ebec02
 
ebec02
 	if (!iff->fip_ready) {
ebec02
 		iff->ps = fip_socket(iff->ifindex, FIP_NONE);
ebec02
+		if (iff->ps < 0) {
ebec02
+			FIP_LOG_DBG("if %d not ready\n", iff->ifindex);
ebec02
+			return 0;
ebec02
+		}
ebec02
 		setsockopt(iff->ps, SOL_PACKET, PACKET_ORIGDEV,
ebec02
 			   &origdev, sizeof(origdev));
ebec02
 		pfd_add(iff->ps);
ebec02
@@ -792,34 +838,23 @@ static int probe_fip_interface(struct iff *iff)
ebec02
 	}
ebec02
 
ebec02
 	if (config.vn2vn)
ebec02
-		fip_send_vlan_request(iff->ps, iff->ifindex, iff->mac_addr,
ebec02
-				      FIP_ALL_VN2VN);
ebec02
+		rc = fip_send_vlan_request(iff->ps, iff->ifindex,
ebec02
+					   iff->mac_addr, FIP_ALL_VN2VN);
ebec02
 	else
ebec02
-		fip_send_vlan_request(iff->ps, iff->ifindex, iff->mac_addr,
ebec02
-				      FIP_ALL_FCF);
ebec02
-	iff->req_sent = true;
ebec02
-	return 0;
ebec02
+		rc = fip_send_vlan_request(iff->ps, iff->ifindex,
ebec02
+					   iff->mac_addr, FIP_ALL_FCF);
ebec02
+	if (rc == 0)
ebec02
+		iff->req_sent = true;
ebec02
+	return rc == 0 ? 0 : 1;
ebec02
 }
ebec02
 
ebec02
 static int send_vlan_requests(void)
ebec02
 {
ebec02
 	struct iff *iff;
ebec02
-	int i;
ebec02
 	int skipped = 0;
ebec02
 
ebec02
-	if (config.automode) {
ebec02
-		TAILQ_FOREACH(iff, &interfaces, list_node) {
ebec02
-			skipped += probe_fip_interface(iff);
ebec02
-		}
ebec02
-	} else {
ebec02
-		for (i = 0; i < config.namec; i++) {
ebec02
-			iff = lookup_iff(0, config.namev[i]);
ebec02
-			if (!iff) {
ebec02
-				skipped++;
ebec02
-				continue;
ebec02
-			}
ebec02
-			skipped += probe_fip_interface(iff);
ebec02
-		}
ebec02
+	TAILQ_FOREACH(iff, &interfaces, list_node) {
ebec02
+		skipped += probe_fip_interface(iff);
ebec02
 	}
ebec02
 	return skipped;
ebec02
 }
ebec02
@@ -829,51 +864,70 @@ static void do_vlan_discovery(void)
ebec02
 	struct iff *iff;
ebec02
 	int retry_count = 0;
ebec02
 	int skip_retry_count = 0;
ebec02
-	int skipped = 0;
ebec02
+	int skipped = 0, retry_iff = 0;
ebec02
 retry:
ebec02
 	skipped += send_vlan_requests();
ebec02
 	if (skipped && skip_retry_count++ < config.link_retry) {
ebec02
-		FIP_LOG_DBG("waiting for IFF_RUNNING [%d]\n", skip_retry_count);
ebec02
+		FIP_LOG_DBG("waiting for IFF_RUNNING [%d/%d]\n",
ebec02
+			    skip_retry_count, config.link_retry);
ebec02
 		recv_loop(500);
ebec02
 		skipped = 0;
ebec02
 		retry_count = 0;
ebec02
 		goto retry;
ebec02
 	}
ebec02
 	recv_loop(200);
ebec02
-	TAILQ_FOREACH(iff, &interfaces, list_node)
ebec02
+	TAILQ_FOREACH(iff, &interfaces, list_node) {
ebec02
+		if (!iff->fip_ready) {
ebec02
+			FIP_LOG_DBG("if %d: skipping, FIP not ready\n",
ebec02
+				    iff->ifindex);
ebec02
+			continue;
ebec02
+		}
ebec02
+		if (!iff->running && iff->linkup_sent) {
ebec02
+			FIP_LOG_DBG("if %d: waiting for IFF_RUNNING [%d]\n",
ebec02
+				    iff->ifindex, retry_count);
ebec02
+			retry_iff++;
ebec02
+			continue;
ebec02
+		}
ebec02
 		/* if we did not receive a response, retry */
ebec02
-		if (iff->req_sent && !iff->resp_recv &&
ebec02
-		    retry_count++ < MAX_VLAN_RETRIES) {
ebec02
-			FIP_LOG_DBG("VLAN discovery RETRY [%d]", retry_count);
ebec02
-			goto retry;
ebec02
+		if (iff->req_sent && !iff->resp_recv) {
ebec02
+			FIP_LOG_DBG("if %d: VLAN discovery RETRY [%d]",
ebec02
+				    iff->ifindex, retry_count);
ebec02
+			iff->req_sent = false;
ebec02
+			retry_iff++;
ebec02
+			continue;
ebec02
 		}
ebec02
+		if (config.create) {
ebec02
+			struct iff *vlan;
ebec02
+
ebec02
+			TAILQ_FOREACH(vlan, &iff->vlans, list_node) {
ebec02
+				if (!vlan->running) {
ebec02
+					FIP_LOG_DBG("vlan %d: waiting for "
ebec02
+						    "IFF_RUNNING [%d]",
ebec02
+						    vlan->ifindex, retry_count);
ebec02
+					retry_iff++;
ebec02
+					continue;
ebec02
+				}
ebec02
+			}
ebec02
+		}
ebec02
+	}
ebec02
+	if (retry_iff && retry_count++ < config.link_retry) {
ebec02
+		recv_loop(1000);
ebec02
+		retry_iff = 0;
ebec02
+		goto retry;
ebec02
+	}
ebec02
 }
ebec02
 
ebec02
 static void cleanup_interfaces(void)
ebec02
 {
ebec02
 	struct iff *iff;
ebec02
-	int i;
ebec02
-	int skipped = 0;
ebec02
 
ebec02
-	if (config.automode) {
ebec02
-		TAILQ_FOREACH(iff, &interfaces, list_node) {
ebec02
-			if (iff->linkup_sent &&
ebec02
-			    (!iff->running || !iff->req_sent || !iff->resp_recv)) {
ebec02
-				FIP_LOG_DBG("shutdown if %d",
ebec02
-					    iff->ifindex);
ebec02
-				rtnl_set_iff_down(iff->ifindex, NULL);
ebec02
-				iff->linkup_sent = false;
ebec02
-			}
ebec02
-		}
ebec02
-	} else {
ebec02
-		for (i = 0; i < config.namec; i++) {
ebec02
-			iff = lookup_iff(0, config.namev[i]);
ebec02
-			if (!iff) {
ebec02
-				skipped++;
ebec02
+	TAILQ_FOREACH(iff, &interfaces, list_node) {
ebec02
+		if (iff->linkup_sent) {
ebec02
+			if (config.link_up && iff->resp_recv)
ebec02
 				continue;
ebec02
-			}
ebec02
-			if (iff->linkup_sent &&
ebec02
-			    (!iff->running || !iff->req_sent || !iff->resp_recv)) {
ebec02
+			if (iff->fcoe_started)
ebec02
+				continue;
ebec02
+			if (TAILQ_EMPTY(&iff->vlans)) {
ebec02
 				FIP_LOG_DBG("shutdown if %d",
ebec02
 					    iff->ifindex);
ebec02
 				rtnl_set_iff_down(iff->ifindex, NULL);
ebec02
@@ -881,8 +935,8 @@ static void cleanup_interfaces(void)
ebec02
 			}
ebec02
 		}
ebec02
 	}
ebec02
-
ebec02
 }
ebec02
+
ebec02
 /* this is to not require headers from libcap */
ebec02
 static inline int capget(cap_user_header_t hdrp, cap_user_data_t datap)
ebec02
 {
ebec02
@@ -934,29 +988,24 @@ int main(int argc, char **argv)
ebec02
 	determine_libfcoe_interface();
ebec02
 
ebec02
 	find_interfaces(ns);
ebec02
-	while ((TAILQ_EMPTY(&interfaces)) && ++find_cnt < 5) {
ebec02
-		FIP_LOG_DBG("no interfaces found, trying again");
ebec02
-		find_interfaces(ns);
ebec02
-	}
ebec02
+	if (config.automode)
ebec02
+		while ((TAILQ_EMPTY(&interfaces)) && ++find_cnt < 5) {
ebec02
+			FIP_LOG_DBG("no interfaces found, trying again");
ebec02
+			find_interfaces(ns);
ebec02
+		}
ebec02
 
ebec02
 	if (TAILQ_EMPTY(&interfaces)) {
ebec02
-		FIP_LOG_ERR(ENODEV, "no interfaces to perform discovery on");
ebec02
+		if (config.automode)
ebec02
+			FIP_LOG_ERR(ENODEV,
ebec02
+				    "no interfaces to perform discovery on");
ebec02
+		else
ebec02
+			FIP_LOG("no interfaces to perform discovery on");
ebec02
 		exit(1);
ebec02
 	}
ebec02
 
ebec02
 	do_vlan_discovery();
ebec02
 
ebec02
 	rc = print_results();
ebec02
-	if (!rc && config.create) {
ebec02
-		create_missing_vlans();
ebec02
-		/*
ebec02
-		 * need to listen for the RTM_NETLINK messages
ebec02
-		 * about the new VLAN devices
ebec02
-		 */
ebec02
-		recv_loop(500);
ebec02
-	}
ebec02
-	if (!rc && config.start)
ebec02
-		start_fcoe();
ebec02
 
ebec02
 	cleanup_interfaces();
ebec02
 
ebec02
diff --git a/lib/fip.c b/lib/fip.c
ebec02
index 73bf03e..6657b61 100644
ebec02
--- a/lib/fip.c
ebec02
+++ b/lib/fip.c
ebec02
@@ -95,10 +95,11 @@ static int fip_get_sanmac(int ifindex, unsigned char *addr)
ebec02
  * @mac: MAC address to add or delete
ebec02
  * @multi: false if unicast, true if multicast address
ebec02
  */
ebec02
-static void
ebec02
+static int
ebec02
 fip_socket_add_addr(int s, int ifindex, bool add, const __u8 *mac, bool multi)
ebec02
 {
ebec02
 	struct packet_mreq mr;
ebec02
+	int rc = 0;
ebec02
 
ebec02
 	memset(&mr, 0, sizeof(mr));
ebec02
 	mr.mr_ifindex = ifindex;
ebec02
@@ -107,9 +108,12 @@ fip_socket_add_addr(int s, int ifindex, bool add, const __u8 *mac, bool multi)
ebec02
 	memcpy(mr.mr_address, mac, ETHER_ADDR_LEN);
ebec02
 	if (setsockopt(s, SOL_PACKET,
ebec02
 		       add ? PACKET_ADD_MEMBERSHIP : PACKET_DROP_MEMBERSHIP,
ebec02
-		       &mr, sizeof(mr)) < 0)
ebec02
+		       &mr, sizeof(mr)) < 0) {
ebec02
 		FIP_LOG_DBG("PACKET_%s_MEMBERSHIP:failed\n",
ebec02
 			    add ? "ADD" : "DROP");
ebec02
+		rc = -errno;
ebec02
+	}
ebec02
+	return rc;
ebec02
 }
ebec02
 
ebec02
 /**
ebec02
@@ -118,16 +122,16 @@ fip_socket_add_addr(int s, int ifindex, bool add, const __u8 *mac, bool multi)
ebec02
  * @ifindex: network interface index to send on
ebec02
  * @add: 1 to add 0 to del
ebec02
  */
ebec02
-static void fip_socket_sanmac(int s, int ifindex, int add)
ebec02
+static int fip_socket_sanmac(int s, int ifindex, int add)
ebec02
 {
ebec02
 	unsigned char smac[ETHER_ADDR_LEN];
ebec02
 
ebec02
 	if (fip_get_sanmac(ifindex, smac)) {
ebec02
 		FIP_LOG_DBG("%s: no sanmac, ifindex %d\n", __func__, ifindex);
ebec02
-		return;
ebec02
+		return -ENXIO;
ebec02
 	}
ebec02
 
ebec02
-	fip_socket_add_addr(s, ifindex, add, smac, false);
ebec02
+	return fip_socket_add_addr(s, ifindex, add, smac, false);
ebec02
 }
ebec02
 
ebec02
 /**
ebec02
@@ -210,7 +214,11 @@ int fip_socket(int ifindex, enum fip_multi multi)
ebec02
 	if (s < 0)
ebec02
 		return s;
ebec02
 
ebec02
-	fip_socket_sanmac(s, ifindex, 1);
ebec02
+	rc = fip_socket_sanmac(s, ifindex, 1);
ebec02
+	if (rc < 0) {
ebec02
+		close(s);
ebec02
+		return rc;
ebec02
+	}
ebec02
 	if (multi != FIP_NONE)
ebec02
 		fip_socket_multi(s, ifindex, true, multi);
ebec02