[iscsi-initiator-utils] rebase to latest upstream (2.0.873+) and iscsiuio

Chris Leech cleech at fedoraproject.org
Tue Jan 22 23:20:32 UTC 2013


commit 0e55d5ba8c35634b5eaef62c36659d08061daf00
Author: Chris Leech <cleech at redhat.com>
Date:   Tue Jan 22 13:44:13 2013 -0800

    rebase to latest upstream (2.0.873+) and iscsiuio

 .gitignore                                         |   18 +-
 ...-fix-iscsid-segfault-during-qla4xxx-login.patch |   43 +
 ...Bring-up-the-corresponding-network-interf.patch |   37 +
 ...-fix-compile-error-when-OFFLOAD_BOOT_SUPP.patch |   35 +
 ...assing-more-net-params-from-ibft-to-iface.patch |   32 +
 ...-Convert-r-argument-to-an-integer-before-.patch |   62 +
 ...ate-README-for-removal-of-DBM-requirement.patch |   49 +
 ...iadm-fix-abstract-socket-length-in-bind-c.patch |   80 +
 ...ement-systemd-compatible-socket-activatio.patch |   79 +
 ...iscsid-add-example-unit-files-for-systemd.patch |   54 +
 ...tools-fix-get_random_bytes-error-handling.patch |   61 +
 ...patch => 0051-update-initscripts-and-docs.patch |   99 +-
 ...r-config.patch => 0052-use-var-for-config.patch |  163 +-
 0053-use-red-hat-for-name.patch                    |   25 +
 ...s-add-libiscsi.patch => 0054-add-libiscsi.patch |  409 +-
 0055-dont-use-static.patch                         |   25 +
 0056-remove-the-offload-boot-supported-ifdef.patch |   45 +
 ...tch => 0057-iscsid-iscsiuio-ipc-interface.patch |  250 +-
 0071-iscsiuio-0.7.4.3.patch                        | 5730 ++
 0072-iscsiuio-0.7.6.1.patch                        |  326 +
 ...-version-string-to-match-RPM-package-vers.patch |   25 +
 iscsi-initiator-utils-add-rh-ver.patch             |   11 -
 iscsi-initiator-utils-brcm-man.patch               |   19 -
 iscsi-initiator-utils-dont-use-openssl.patch       |   47 -
 iscsi-initiator-utils-dont-use-static.patch        |   12 -
 iscsi-initiator-utils-fix-default-bindings.patch   |  172 -
 iscsi-initiator-utils-fix-ipv6-boot.patch          |   33 -
 iscsi-initiator-utils-fix-iscsiadm-return.patch    |   13 -
 iscsi-initiator-utils-fix-nlmsglen.patch           |   12 -
 iscsi-initiator-utils-ofl-iface-fixes.patch        |  471 -
 ...s-remove-the-offload-boot-supported-ifdef.patch |   46 -
 iscsi-initiator-utils-sync-iscsi.patch             |16516 -----
 iscsi-initiator-utils-sync-uio-0.7.0.14.patch      |  371 -
 iscsi-initiator-utils-sync-uio-0.7.0.8.patch       |74274 --------------------
 ...ator-utils-uio-handle-different-iface_rec.patch |  137 -
 iscsi-initiator-utils-use-red-hat-for-name.patch   |   12 -
 iscsi-initiator-utils.spec                         |  135 +-
 sources                                            |    3 +-
 38 files changed, 7318 insertions(+), 92613 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 5ae3769..68ed4c3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,16 +1,2 @@
-open-iscsi-5.0.4.446.tar.gz
-open-iscsi-5.0.5.476.tar.bz2
-open-iscsi-5.0.5.595.tar.bz2
-open-iscsi-6.0.5.595.tar.bz2
-open-iscsi-1.1-645.tar.bz2
-open-iscsi-6.1.1.645.tar.bz2
-open-iscsi-6.1.1.685.tar.bz2
-open-iscsi-6.2.0.695.tar.bz2
-open-iscsi-2.0-754.tar.gz
-open-iscsi-2.0-865.2.tar.gz
-open-iscsi-2.0-865.13.tar.gz
-open-iscsi-2.0-868-test1.tar.gz
-open-iscsi-2.0-870-rc1.tar.gz
-open-iscsi-2.0-870.1.tar.gz
-open-iscsi-2.0-872-rc1-bnx2i.tar.gz
-open-iscsi-2.0-872-rc4-bnx2i.tar.gz
+/open-iscsi-2.0-873.tar.gz
+/iscsiuio-0.7.2.1.tar.gz
diff --git a/0001-iscsid-fix-iscsid-segfault-during-qla4xxx-login.patch b/0001-iscsid-fix-iscsid-segfault-during-qla4xxx-login.patch
new file mode 100644
index 0000000..eabacbb
--- /dev/null
+++ b/0001-iscsid-fix-iscsid-segfault-during-qla4xxx-login.patch
@@ -0,0 +1,43 @@
+From 71cd021b74a7094b5186a42bfe59a35e2fa66018 Mon Sep 17 00:00:00 2001
+From: Mike Christie <michaelc at cs.wisc.edu>
+Date: Wed, 5 Sep 2012 16:18:16 -0500
+Subject: iscsid: fix iscsid segfault during qla4xxx login
+
+If the kernel sends multiple ISCSI_KEVENT_CONN_LOGIN_STATE
+events for the same login event iscsid will segault.
+
+When we get a conn error we will set the r_stage to reopen, then when
+session_conn_process_login handles the first login event we set the r_stage
+to R_STAGE_NO_CHANGE. But then it looks like if we get a second login event
+r_stage is no_change and session_conn_process_login will run again and
+call mgmt_ipc_write_rsp on a bad qtask.
+---
+ usr/initiator.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/usr/initiator.c b/usr/initiator.c
+index 79ca32c..d475358 100644
+--- a/usr/initiator.c
++++ b/usr/initiator.c
+@@ -993,7 +993,7 @@ static void session_scan_host(struct iscsi_session *session, int hostno,
+ 		exit(0);
+ 	} else if (pid > 0) {
+ 		reap_inc();
+-		if (qtask) {
++		if (qtask && qtask->mgmt_ipc_fd >= 0) {
+ 			close(qtask->mgmt_ipc_fd);
+ 			free(qtask);
+ 		}
+@@ -1618,6 +1618,9 @@ static void session_conn_process_login(void *data)
+ 	if (state == ISCSI_CONN_STATE_FREE)
+ 		goto failed_login;
+ 
++	if (conn->state == ISCSI_CONN_STATE_LOGGED_IN)
++		return;
++
+ 	conn->state = ISCSI_CONN_STATE_LOGGED_IN;
+ 	/*
+ 	 * ok we were in_login and now we got the notification that we are
+-- 
+1.7.11.7
+
diff --git a/0002-ISCSISTART-Bring-up-the-corresponding-network-interf.patch b/0002-ISCSISTART-Bring-up-the-corresponding-network-interf.patch
new file mode 100644
index 0000000..844babf
--- /dev/null
+++ b/0002-ISCSISTART-Bring-up-the-corresponding-network-interf.patch
@@ -0,0 +1,37 @@
+From f0a8c95426d21413d9980d31740e193208e3280e Mon Sep 17 00:00:00 2001
+From: Eddie Wai <eddie.wai at broadcom.com>
+Date: Wed, 5 Sep 2012 14:14:20 -0700
+Subject: ISCSISTART: Bring up the corresponding network interface for iboot
+
+This is needed for the iSCSI offload boot.
+
+Snip from M. Christie:
+Note that we must bring up the interface before iface_setup_from_boot_context,
+because we will want iscsi_sysfs_get_host_no_from_hwaddress to be able to match
+a MAC to a iscsi host.  For some bnx2i cards, the card has to be ifupd for the
+iscsi interface to have a MAC. If it is not ifupd we have seen MACs with all
+zeros or no iscsi_hosts on different cards.
+
+Signed-off-by: Eddie Wai <eddie.wai at broadcom.com>
+---
+ usr/iface.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/usr/iface.c b/usr/iface.c
+index 3a9582e..4028e34 100644
+--- a/usr/iface.c
++++ b/usr/iface.c
+@@ -917,6 +917,10 @@ int iface_setup_from_boot_context(struct iface_rec *iface,
+ 							transport_name))
+ 			t = iscsi_sysfs_get_transport_by_name(transport_name);
+ 
++		if (net_ifup_netdev(context->iface))
++			log_warning("Could not bring up netdev %s for boot",
++				    context->iface);
++
+ 		hostno = iscsi_sysfs_get_host_no_from_hwaddress(context->mac,
+ 								&rc);
+ 		if (rc) {
+-- 
+1.7.11.7
+
diff --git a/0003-iscsi-tools-fix-compile-error-when-OFFLOAD_BOOT_SUPP.patch b/0003-iscsi-tools-fix-compile-error-when-OFFLOAD_BOOT_SUPP.patch
new file mode 100644
index 0000000..c80ff3a
--- /dev/null
+++ b/0003-iscsi-tools-fix-compile-error-when-OFFLOAD_BOOT_SUPP.patch
@@ -0,0 +1,35 @@
+From d81fd4903cebb1d00aa48b0718d20e34b00dfde1 Mon Sep 17 00:00:00 2001
+From: Mike Christie <michaelc at cs.wisc.edu>
+Date: Wed, 26 Sep 2012 21:19:39 -0500
+Subject: iscsi tools: fix compile error when OFFLOAD_BOOT_SUPPORT defined
+
+Fix compile error when OFFLOAD_BOOT_SUPPORT is defined and fix
+warning when it is defined.
+---
+ usr/iface.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/usr/iface.c b/usr/iface.c
+index 4028e34..4f81a76 100644
+--- a/usr/iface.c
++++ b/usr/iface.c
+@@ -894,7 +894,6 @@ int iface_setup_from_boot_context(struct iface_rec *iface,
+ 				   struct boot_context *context)
+ {
+ 	struct iscsi_transport *t = NULL;
+-	char transport_name[ISCSI_TRANSPORT_NAME_MAXLEN];
+ 	uint32_t hostno;
+ 
+ 	if (strlen(context->initiatorname))
+@@ -910,6 +909,8 @@ int iface_setup_from_boot_context(struct iface_rec *iface,
+ 	} else if (strlen(context->iface)) {
+ /* this ifdef is only temp until distros and firmwares are updated */
+ #ifdef OFFLOAD_BOOT_SUPPORTED
++		char transport_name[ISCSI_TRANSPORT_NAME_MAXLEN];
++		int rc;
+ 
+ 		memset(transport_name, 0, ISCSI_TRANSPORT_NAME_MAXLEN);
+ 		/* make sure offload driver is loaded */
+-- 
+1.7.11.7
+
diff --git a/0004-ISCSID-Passing-more-net-params-from-ibft-to-iface.patch b/0004-ISCSID-Passing-more-net-params-from-ibft-to-iface.patch
new file mode 100644
index 0000000..5de8d3e
--- /dev/null
+++ b/0004-ISCSID-Passing-more-net-params-from-ibft-to-iface.patch
@@ -0,0 +1,32 @@
+From 13d08e79090421fbf67fd727aada487ea23ecc2d Mon Sep 17 00:00:00 2001
+From: Eddie Wai <eddie.wai at broadcom.com>
+Date: Thu, 27 Sep 2012 13:57:12 -0700
+Subject: ISCSID: Passing more net params from ibft to iface
+
+Added the passing of the vlan_id, subnet_mask, and gateway attributes
+from the ibft context to the iface struct for the connection request.
+
+Signed-off-by: Eddie Wai <eddie.wai at broadcom.com>
+---
+ usr/iface.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/usr/iface.c b/usr/iface.c
+index 4f81a76..c86892e 100644
+--- a/usr/iface.c
++++ b/usr/iface.c
+@@ -962,6 +962,11 @@ int iface_setup_from_boot_context(struct iface_rec *iface,
+ 		sizeof(iface->hwaddress));
+ 	strlcpy(iface->ipaddress, context->ipaddr,
+ 		sizeof(iface->ipaddress));
++	iface->vlan_id = atoi(context->vlan);
++	strlcpy(iface->subnet_mask, context->mask,
++		sizeof(iface->subnet_mask));
++	strlcpy(iface->gateway, context->gateway,
++		sizeof(iface->gateway));
+ 	log_debug(1, "iface " iface_fmt "\n", iface_str(iface));
+ 	return 1;
+ }
+-- 
+1.7.11.7
+
diff --git a/0005-iscsi-tools-Convert-r-argument-to-an-integer-before-.patch b/0005-iscsi-tools-Convert-r-argument-to-an-integer-before-.patch
new file mode 100644
index 0000000..4a95ac1
--- /dev/null
+++ b/0005-iscsi-tools-Convert-r-argument-to-an-integer-before-.patch
@@ -0,0 +1,62 @@
+From 9dd181dcb1ca299cd82075b8e598fc57d87ee1c0 Mon Sep 17 00:00:00 2001
+From: Jim Ramsay <jim_ramsay at dell.com>
+Date: Wed, 3 Oct 2012 09:57:43 -0400
+Subject: iscsi tools: Convert '-r' argument to an integer before checking if
+ it is a path
+
+If there is a file in the CWD named '1' and you were trying to run
+'iscsiadm -m session -r 1 ...', the command would fail with "1 is not a
+directory".
+
+Root cause: The code that parses the -r option's argument tries lstat(2)
+first, falling back to atoi(3) only if lstat fails.
+
+This change inverts the order of checks, first with strtol(3) to see if
+the argument given is a positive integer, then falling back to lstat(2)
+only if it is not.
+
+Signed-off-by: Jim Ramsay <jim_ramsay at dell.com>
+---
+ usr/iscsi_sysfs.c | 17 +++++++++--------
+ 1 file changed, 9 insertions(+), 8 deletions(-)
+
+diff --git a/usr/iscsi_sysfs.c b/usr/iscsi_sysfs.c
+index 123dde3..4015b35 100644
+--- a/usr/iscsi_sysfs.c
++++ b/usr/iscsi_sysfs.c
+@@ -740,7 +740,7 @@ int iscsi_sysfs_session_has_leadconn(uint32_t sid)
+  * /sys/devices/platform/hostH/sessionS/targetH:B:I
+  * /sys/devices/platform/hostH/sessionS
+  *
+- * return the sid S. If just the sid is passed in it will be covnerted
++ * return the sid S. If just the sid is passed in it will be converted
+  * to a int.
+  */
+ int iscsi_sysfs_get_sid_from_path(char *session)
+@@ -748,15 +748,16 @@ int iscsi_sysfs_get_sid_from_path(char *session)
+ 	struct sysfs_device *dev_parent, *dev;
+ 	struct stat statb;
+ 	char devpath[PATH_SIZE];
++	char *end;
++	int sid;
++
++	sid = strtol(session, &end, 10);
++	if (sid > 0 && *session != '\0' && *end == '\0')
++		return sid;
+ 
+ 	if (lstat(session, &statb)) {
+-		log_debug(1, "Could not stat %s failed with %d",
+-			  session, errno);
+-		if (index(session, '/')) {
+-			log_error("%s is an invalid session path\n", session);
+-			exit(1);
+-		}
+-		return atoi(session);
++		log_error("%s is an invalid session ID or path\n", session);
++		exit(1);
+ 	}
+ 
+ 	if (!S_ISDIR(statb.st_mode) && !S_ISLNK(statb.st_mode)) {
+-- 
+1.7.11.7
+
diff --git a/0006-Update-README-for-removal-of-DBM-requirement.patch b/0006-Update-README-for-removal-of-DBM-requirement.patch
new file mode 100644
index 0000000..3fb2408
--- /dev/null
+++ b/0006-Update-README-for-removal-of-DBM-requirement.patch
@@ -0,0 +1,49 @@
+From 97db3db45c7e96888ea48a54ff19b7ff5d08cca6 Mon Sep 17 00:00:00 2001
+From: Andy Grover <agrover at redhat.com>
+Date: Wed, 24 Oct 2012 15:37:28 -0700
+Subject: Update README for removal of DBM requirement
+
+Removed in 093b1f4 (2006)
+
+Signed-off-by: Andy Grover <agrover at redhat.com>
+---
+ README | 23 ++++++++++++++---------
+ 1 file changed, 14 insertions(+), 9 deletions(-)
+
+diff --git a/README b/README
+index 7364b2d..ec22098 100644
+--- a/README
++++ b/README
+@@ -159,15 +159,20 @@ Usage: iscsid [OPTION]
+ 5. Open-iSCSI Configuration Utility
+ ===================================
+ 
+-Open-iSCSI persistent configuration is implemented as a DBM database
+-available on all Linux installations.
+-
+-The database contains two tables:
+-
+-- Discovery table (/etc/iscsi/send_targets);
+-- Node table (/etc/iscsi/nodes).
+-
+-The regular place for iSCSI database files: /etc/iscsi/nodes
++Open-iSCSI persistent configuration is stored in a number of
++directories under a configuration root directory, using a flat-file
++format. This configuration root directory is /etc/iscsi by default,
++but may also commonly be in /var/lib/iscsi.
++
++Configuration is contained in directories for:
++
++- nodes
++- slp
++- isns
++- static
++- fw
++- send_targets
++- ifaces
+ 
+ The iscsiadm utility is a command-line tool to manage (update, delete,
+ insert, query) the persistent database.
+-- 
+1.7.11.7
+
diff --git a/0007-iscsid-iscsiadm-fix-abstract-socket-length-in-bind-c.patch b/0007-iscsid-iscsiadm-fix-abstract-socket-length-in-bind-c.patch
new file mode 100644
index 0000000..53ade5f
--- /dev/null
+++ b/0007-iscsid-iscsiadm-fix-abstract-socket-length-in-bind-c.patch
@@ -0,0 +1,80 @@
+From 2d086a831dc16d10729d6fce17bed3ade3efd16c Mon Sep 17 00:00:00 2001
+From: Tomasz Torcz <tomek at pipebreaker.pl>
+Date: Wed, 28 Nov 2012 13:37:06 +0100
+Subject: iscsid,iscsiadm: fix abstract socket length in bind() call
+
+For abstract sockets, the addrlen parameter should be the actual
+length of socket's name.  Otherwise socket gets padded with some
+number of NULs.
+---
+ usr/iscsid_req.c | 10 ++++++----
+ usr/mgmt_ipc.c   |  9 +++++----
+ 2 files changed, 11 insertions(+), 8 deletions(-)
+
+diff --git a/usr/iscsid_req.c b/usr/iscsid_req.c
+index 0902011..1c4678d 100644
+--- a/usr/iscsid_req.c
++++ b/usr/iscsid_req.c
+@@ -56,7 +56,7 @@ static void iscsid_startup(void)
+ 
+ static int iscsid_connect(int *fd, int start_iscsid)
+ {
+-	int nsec;
++	int nsec, addr_len;
+ 	struct sockaddr_un addr;
+ 
+ 	*fd = socket(AF_LOCAL, SOCK_STREAM, 0);
+@@ -65,15 +65,17 @@ static int iscsid_connect(int *fd, int start_iscsid)
+ 		return ISCSI_ERR_ISCSID_NOTCONN;
+ 	}
+ 
++	addr_len = offsetof(struct sockaddr_un, sun_path) + strlen(ISCSIADM_NAMESPACE) + 1;
++
+ 	memset(&addr, 0, sizeof(addr));
+ 	addr.sun_family = AF_LOCAL;
+-	memcpy((char *) &addr.sun_path + 1, ISCSIADM_NAMESPACE,
+-		strlen(ISCSIADM_NAMESPACE));
++	memcpy((char *) &addr.sun_path + 1, ISCSIADM_NAMESPACE, addr_len);
++
+ 	/*
+ 	 * Trying to connect with exponential backoff
+ 	 */
+ 	for (nsec = 1; nsec <= MAXSLEEP; nsec <<= 1) {
+-		if (connect(*fd, (struct sockaddr *) &addr, sizeof(addr)) == 0)
++		if (connect(*fd, (struct sockaddr *) &addr, addr_len) == 0)
+ 			/* Connection established */
+ 			return ISCSI_SUCCESS;
+ 
+diff --git a/usr/mgmt_ipc.c b/usr/mgmt_ipc.c
+index 5c39c2e..a1dafc9 100644
+--- a/usr/mgmt_ipc.c
++++ b/usr/mgmt_ipc.c
+@@ -43,7 +43,7 @@
+ int
+ mgmt_ipc_listen(void)
+ {
+-	int fd, err;
++	int fd, err, addr_len;
+ 	struct sockaddr_un addr;
+ 
+ 	fd = socket(AF_LOCAL, SOCK_STREAM, 0);
+@@ -52,12 +52,13 @@ mgmt_ipc_listen(void)
+ 		return fd;
+ 	}
+ 
++	addr_len = offsetof(struct sockaddr_un, sun_path) + strlen(ISCSIADM_NAMESPACE) + 1;
++
+ 	memset(&addr, 0, sizeof(addr));
+ 	addr.sun_family = AF_LOCAL;
+-	memcpy((char *) &addr.sun_path + 1, ISCSIADM_NAMESPACE,
+-		strlen(ISCSIADM_NAMESPACE));
++	memcpy((char *) &addr.sun_path + 1, ISCSIADM_NAMESPACE, addr_len);
+ 
+-	if ((err = bind(fd, (struct sockaddr *) &addr, sizeof(addr))) < 0) {
++	if ((err = bind(fd, (struct sockaddr *) &addr, addr_len)) < 0 ) {
+ 		log_error("Can not bind IPC socket");
+ 		close(fd);
+ 		return err;
+-- 
+1.7.11.7
+
diff --git a/0008-iscsid-implement-systemd-compatible-socket-activatio.patch b/0008-iscsid-implement-systemd-compatible-socket-activatio.patch
new file mode 100644
index 0000000..2e4715c
--- /dev/null
+++ b/0008-iscsid-implement-systemd-compatible-socket-activatio.patch
@@ -0,0 +1,79 @@
+From 5d0e19fcc1cea77a72647cf96c5d3d773e8ee277 Mon Sep 17 00:00:00 2001
+From: Tomasz Torcz <tomek at pipebreaker.pl>
+Date: Wed, 28 Nov 2012 13:37:07 +0100
+Subject: iscsid: implement systemd-compatible socket activation
+
+---
+ usr/mgmt_ipc.c | 29 +++++++++++++++++++++++++++++
+ usr/mgmt_ipc.h |  1 +
+ 2 files changed, 30 insertions(+)
+
+diff --git a/usr/mgmt_ipc.c b/usr/mgmt_ipc.c
+index a1dafc9..87bd346 100644
+--- a/usr/mgmt_ipc.c
++++ b/usr/mgmt_ipc.c
+@@ -39,6 +39,7 @@
+ 
+ #define PEERUSER_MAX	64
+ #define EXTMSG_MAX	(64 * 1024)
++#define SD_SOCKET_FDS_START 3
+ 
+ int
+ mgmt_ipc_listen(void)
+@@ -46,6 +47,12 @@ mgmt_ipc_listen(void)
+ 	int fd, err, addr_len;
+ 	struct sockaddr_un addr;
+ 
++	/* first check if we have fd handled by systemd */
++	fd = mgmt_ipc_systemd();
++	if (fd >= 0)
++		return fd;
++
++	/* manually establish a socket */
+ 	fd = socket(AF_LOCAL, SOCK_STREAM, 0);
+ 	if (fd < 0) {
+ 		log_error("Can not create IPC socket");
+@@ -73,6 +80,28 @@ mgmt_ipc_listen(void)
+ 	return fd;
+ }
+ 
++int mgmt_ipc_systemd(void)
++{
++	const char *env;
++
++	env = getenv("LISTEN_PID");
++
++	if (!env || (strtoul(env, NULL, 10) != getpid()))
++		return -EINVAL;
++
++	env = getenv("LISTEN_FDS");
++
++	if (!env)
++		return -EINVAL;
++
++	if (strtoul(env, NULL, 10) != 1) {
++		log_error("Did not receive exactly one IPC socket from systemd");
++		return -EINVAL;
++	}
++
++	return SD_SOCKET_FDS_START;
++}
++
+ void
+ mgmt_ipc_close(int fd)
+ {
+diff --git a/usr/mgmt_ipc.h b/usr/mgmt_ipc.h
+index 7d8ce72..55972ed 100644
+--- a/usr/mgmt_ipc.h
++++ b/usr/mgmt_ipc.h
+@@ -112,6 +112,7 @@ typedef int mgmt_ipc_fn_t(struct queue_task *);
+ struct queue_task;
+ void mgmt_ipc_write_rsp(struct queue_task *qtask, int err);
+ int mgmt_ipc_listen(void);
++int mgmt_ipc_systemd(void);
+ void mgmt_ipc_close(int fd);
+ void mgmt_ipc_handle(int accept_fd);
+ 
+-- 
+1.7.11.7
+
diff --git a/0009-iscsid-add-example-unit-files-for-systemd.patch b/0009-iscsid-add-example-unit-files-for-systemd.patch
new file mode 100644
index 0000000..28b9b78
--- /dev/null
+++ b/0009-iscsid-add-example-unit-files-for-systemd.patch
@@ -0,0 +1,54 @@
+From c34e0bdcbafdb6f9304e1474d51fe1c789c5dea2 Mon Sep 17 00:00:00 2001
+From: Tomasz Torcz <tomek at pipebreaker.pl>
+Date: Wed, 28 Nov 2012 13:37:08 +0100
+Subject: iscsid: add example unit files for systemd
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Those two units, based on the work by Jóhann B. Guðmundsson, exploit
+on-demand socket activation in iscsid.
+---
+ etc/systemd/iscsid.service | 13 +++++++++++++
+ etc/systemd/iscsid.socket  |  9 +++++++++
+ 2 files changed, 22 insertions(+)
+ create mode 100644 etc/systemd/iscsid.service
+ create mode 100644 etc/systemd/iscsid.socket
+
+diff --git a/etc/systemd/iscsid.service b/etc/systemd/iscsid.service
+new file mode 100644
+index 0000000..028e0b3
+--- /dev/null
++++ b/etc/systemd/iscsid.service
+@@ -0,0 +1,13 @@
++[Unit]
++Description=Open-iSCSI
++Documentation=man:iscsid(8) man:iscsiuio(8) man:iscsiadm(8)
++After=network.target NetworkManager-wait-online.service iscsiuio.service tgtd.service targetcli.service
++
++[Service]
++Type=forking
++PIDFile=/var/run/iscsid.pid
++ExecStart=/usr/sbin/iscsid
++ExecStop=/sbin/iscsiadm -k 0 2
++
++[Install]
++WantedBy=multi-user.target
+diff --git a/etc/systemd/iscsid.socket b/etc/systemd/iscsid.socket
+new file mode 100644
+index 0000000..832451d
+--- /dev/null
++++ b/etc/systemd/iscsid.socket
+@@ -0,0 +1,9 @@
++[Unit]
++Description=Open-iSCSI iscsid Socket
++Documentation=man:iscsid(8) man:iscsiuio(8) man:iscsiadm(8)
++
++[Socket]
++ListenStream=@ISCSIADM_ABSTRACT_NAMESPACE
++
++[Install]
++WantedBy=sockets.target
+-- 
+1.7.11.7
+
diff --git a/0010-iscsi-tools-fix-get_random_bytes-error-handling.patch b/0010-iscsi-tools-fix-get_random_bytes-error-handling.patch
new file mode 100644
index 0000000..a177796
--- /dev/null
+++ b/0010-iscsi-tools-fix-get_random_bytes-error-handling.patch
@@ -0,0 +1,61 @@
+From a7afdf46c3193eb102cc6ec2a3b61e8d36794437 Mon Sep 17 00:00:00 2001
+From: Mike Christie <michaelc at cs.wisc.edu>
+Date: Fri, 14 Dec 2012 12:40:27 -0600
+Subject: iscsi tools: fix get_random_bytes error handling
+
+Bug report from Rahul:
+
+There seems to be a bug in function get_random_bytes(). I reported
+this earlier as well but somehow it didn't appear here.
+
+get_random_bytes(unsigned char *data, unsigned int length)
+{
+	long r;
+        unsigned n;
+	int fd;
+
+	fd = open("/dev/urandom", O_RDONLY);
+        	while (length > 0) {
+
+	if (!fd || read(fd, &r, sizeof(long)) != -1)      <<<< the condition is
+incorrect
+---
+ usr/auth.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/usr/auth.c b/usr/auth.c
+index c924545..4ff0425 100644
+--- a/usr/auth.c
++++ b/usr/auth.c
+@@ -189,24 +189,24 @@ get_random_bytes(unsigned char *data, unsigned int length)
+ 
+ 	long r;
+         unsigned n;
+-	int fd;
++	int fd, r_size = sizeof(r);
+ 
+ 	fd = open("/dev/urandom", O_RDONLY);
+         while (length > 0) {
+ 
+-		if (!fd || read(fd, &r, sizeof(long)) != -1)
++		if (fd == -1 || read(fd, &r, r_size) != r_size)
+ 			r = rand();
+                 r = r ^ (r >> 8);
+                 r = r ^ (r >> 4);
+                 n = r & 0x7;
+ 
+-		if (!fd || read(fd, &r, sizeof(long)) != -1)
++		if (fd == -1 || read(fd, &r, r_size) != r_size)
+ 			r = rand();
+                 r = r ^ (r >> 8);
+                 r = r ^ (r >> 5);
+                 n = (n << 3) | (r & 0x7);
+ 
+-		if (!fd || read(fd, &r, sizeof(long)) != -1)
++		if (fd == -1 || read(fd, &r, r_size) != r_size)
+ 			r = rand();
+                 r = r ^ (r >> 8);
+                 r = r ^ (r >> 5);
+-- 
+1.7.11.7
+
diff --git a/iscsi-initiator-utils-update-initscripts-and-docs.patch b/0051-update-initscripts-and-docs.patch
similarity index 76%
rename from iscsi-initiator-utils-update-initscripts-and-docs.patch
rename to 0051-update-initscripts-and-docs.patch
index 90f4117..dc42844 100644
--- a/iscsi-initiator-utils-update-initscripts-and-docs.patch
+++ b/0051-update-initscripts-and-docs.patch
@@ -1,6 +1,52 @@
-diff -aurp open-iscsi-2.0-872-rc4-bnx2i.base/etc/iscsid.conf open-iscsi-2.0-872-rc4-bnx2i.build/etc/iscsid.conf
---- open-iscsi-2.0-872-rc4-bnx2i.base/etc/iscsid.conf	2011-08-14 16:33:53.000000000 -0500
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/etc/iscsid.conf	2011-08-14 16:37:47.000000000 -0500
+From 9e68a86626e9085af1d7a457bf28d2347c0d9356 Mon Sep 17 00:00:00 2001
+From: Chris Leech <cleech at redhat.com>
+Date: Mon, 19 Nov 2012 16:37:13 -0800
+Subject: update initscripts and docs
+
+---
+ README          |  9 +++------
+ etc/iscsid.conf | 23 +++++++++++------------
+ usr/idbm.c      |  4 ++++
+ 3 files changed, 18 insertions(+), 18 deletions(-)
+
+diff --git a/README b/README
+index ec22098..2a8319a 100644
+--- a/README
++++ b/README
+@@ -74,11 +74,6 @@ the cache sync command will fail.
+ - iscsiadm's -P 3 option will not print out scsi devices.
+ - iscsid will not automatically online devices.
+ 
+-You need to enable "Cryptographic API" under "Cryptographic options" in the
+-kernel config. And you must enable "CRC32c CRC algorithm" even if
+-you do not use header or data digests. They are the kernel options,
+-CONFIG_CRYPTO and CONFIG_CRYPTO_CRC32C, respectively.
+-
+ By default the kernel's iSCSI modules will be used. Running:
+ 
+ 	make
+@@ -997,7 +992,7 @@ Red Hat or Fedora:
+ -----------------
+ To start open-iscsi in Red Hat/Fedora you can do:
+ 
+-	service open-iscsi start
++	service iscsi start
+ 
+ To get open-iscsi to automatically start at run time you may have to
+ run:
+@@ -1205,6 +1200,8 @@ iscsid will only perform rediscovery when it gets a SCN from the server.
+ #   linux-isns (SLES's iSNS server) where it sometimes does not send SCN
+ #   events in the proper format, so they may not get handled.
+ 
++To set the startup value, so that nodes are not logged into automatically
++use the value "manual".
+ 
+ Example:
+ --------
+diff --git a/etc/iscsid.conf b/etc/iscsid.conf
+index ef76dc0..ac1d231 100644
+--- a/etc/iscsid.conf
++++ b/etc/iscsid.conf
 @@ -17,10 +17,10 @@
  # maintainers.
  #
@@ -25,7 +71,7 @@ diff -aurp open-iscsi-2.0-872-rc4-bnx2i.base/etc/iscsid.conf open-iscsi-2.0-872-
  
  # For "automatic" startup nodes, setting this to "Yes" will try logins on each
  # available iface until one succeeds, and then stop.  The default "No" will try
-@@ -259,28 +259,27 @@ node.conn[0].iscsi.MaxXmitDataSegmentLen
+@@ -259,28 +259,27 @@ node.conn[0].iscsi.MaxXmitDataSegmentLength = 0
  discovery.sendtargets.iscsi.MaxRecvDataSegmentLength = 32768
  
  # To allow the targets to control the setting of the digest checking,
@@ -61,43 +107,11 @@ diff -aurp open-iscsi-2.0-872-rc4-bnx2i.base/etc/iscsid.conf open-iscsi-2.0-872-
  
  # For multipath configurations, you may want more than one session to be
  # created on each iface record.  If node.session.nr_sessions is greater
-diff -aurp open-iscsi-2.0-872-rc4-bnx2i.base/README open-iscsi-2.0-872-rc4-bnx2i.build/README
---- open-iscsi-2.0-872-rc4-bnx2i.base/README	2011-08-14 16:33:53.000000000 -0500
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/README	2011-08-14 16:34:12.000000000 -0500
-@@ -74,11 +74,6 @@ the cache sync command will fail.
- - iscsiadm's -P 3 option will not print out scsi devices.
- - iscsid will not automatically online devices.
- 
--You need to enable "Cryptographic API" under "Cryptographic options" in the
--kernel config. And you must enable "CRC32c CRC algorithm" even if
--you do not use header or data digests. They are the kernel options,
--CONFIG_CRYPTO and CONFIG_CRYPTO_CRC32C, respectively.
--
- By default the kernel source found at
- /lib/modules/`uname -a`/build
- will be used to compile the open-iscsi modules. To specify a different
-@@ -975,7 +970,7 @@ Red Hat or Fedora:
- -----------------
- To start open-iscsi in Red Hat/Fedora you can do:
- 
--	service open-iscsi start
-+	service iscsi start
- 
- To get open-iscsi to automatically start at run time you may have to
- run:
-@@ -1183,6 +1178,8 @@ iscsid will only perform rediscovery whe
- #   linux-isns (SLES's iSNS server) where it sometimes does not send SCN
- #   events in the proper format, so they may not get handled.
- 
-+To set the startup value, so that nodes are not logged into automatically
-+use the value "manual".
- 
- Example:
- --------
-diff -aurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/idbm.c open-iscsi-2.0-872-rc4-bnx2i.build/usr/idbm.c
---- open-iscsi-2.0-872-rc4-bnx2i.base/usr/idbm.c	2011-08-14 16:33:53.000000000 -0500
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/usr/idbm.c	2011-08-14 16:34:12.000000000 -0500
-@@ -373,9 +373,13 @@ idbm_recinfo_node(node_rec_t *r, recinfo
+diff --git a/usr/idbm.c b/usr/idbm.c
+index 4d30aa9..a1d7d37 100644
+--- a/usr/idbm.c
++++ b/usr/idbm.c
+@@ -399,9 +399,13 @@ idbm_recinfo_node(node_rec_t *r, recinfo_t *ri)
  				 IDBM_SHOW, "None", "CRC32C", "CRC32C,None",
  				 "None,CRC32C", num, 1);
  		sprintf(key, CONN_DATA_DIGEST, i);
@@ -111,3 +125,6 @@ diff -aurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/idbm.c open-iscsi-2.0-872-rc4-b
  		sprintf(key, CONN_IFMARKER, i);
  		__recinfo_int_o2(key, ri, r, conn[i].iscsi.IFMarker, IDBM_SHOW,
  				"No", "Yes", num, 1);
+-- 
+1.7.11.7
+
diff --git a/iscsi-initiator-utils-use-var-for-config.patch b/0052-use-var-for-config.patch
similarity index 74%
rename from iscsi-initiator-utils-use-var-for-config.patch
rename to 0052-use-var-for-config.patch
index 06866a0..83d6938 100644
--- a/iscsi-initiator-utils-use-var-for-config.patch
+++ b/0052-use-var-for-config.patch
@@ -1,55 +1,31 @@
-diff -aurp open-iscsi-2.0-872-rc4-bnx2i.base/doc/iscsiadm.8 open-iscsi-2.0-872-rc4-bnx2i.build/doc/iscsiadm.8
---- open-iscsi-2.0-872-rc4-bnx2i.base/doc/iscsiadm.8	2011-08-14 16:33:53.000000000 -0500
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/doc/iscsiadm.8	2011-08-14 16:41:07.000000000 -0500
-@@ -57,7 +57,7 @@ MAC address of a scsi host.
- .TP
- \fB\-I\fR, \fB\-\-interface=\fI[iface]\fR
- The interface argument specifies the iSCSI interface to use for the operation.
--iSCSI interfaces (iface) are defined in /etc/iscsi/ifaces. For hardware
-+iSCSI interfaces (iface) are defined in /var/lib/iscsi/ifaces. For hardware
- iSCSI (qla4xxx) the iface config must have the hardware address
- (iface.hwaddress = port's MAC address)
- and the driver/transport_name (iface.transport_name). The iface's name is
-@@ -134,7 +134,7 @@ If no other options are specified: for \
- of their respective records are displayed; for \fIsession\fR, all active
- sessions and connections are displayed; for \fIfw\fR, all boot firmware
- values are displayed; for \fIhost\fR, all iSCSI hosts are displayed; and
--for \fIiface\fR, all ifaces setup in /etc/iscsi/ifaces are displayed.
-+for \fIiface\fR, all ifaces setup in /var/lib/iscsi/ifaces are displayed.
- 
- .TP
- \fB\-n\fR, \fB\-\-name=\fIname\fR
-@@ -503,10 +503,10 @@ The configuration file read by \fBiscsid
- The file containing the iSCSI InitiatorName and InitiatorAlias read by
- \fBiscsid\fR and \fBiscsiadm\fR on startup.
- .TP
--/etc/iscsi/nodes/
-+/var/lib/iscsi/nodes/
- This directory contains the nodes with their targets.
- .TP
--/etc/iscsi/send_targets
-+/var/lib/iscsi/send_targets
- This directory contains the portals.
- 
- .SH "SEE ALSO"
-diff -aurp open-iscsi-2.0-872-rc4-bnx2i.base/README open-iscsi-2.0-872-rc4-bnx2i.build/README
---- open-iscsi-2.0-872-rc4-bnx2i.base/README	2011-08-14 16:41:23.000000000 -0500
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/README	2011-08-14 16:42:47.000000000 -0500
-@@ -144,10 +144,10 @@ available on all Linux installations.
- 
- The database contains two tables:
- 
--- Discovery table (/etc/iscsi/send_targets);
--- Node table (/etc/iscsi/nodes).
-+- Discovery table (/var/lib/iscsi/send_targets);
-+- Node table (/var/lib/iscsi/nodes).
- 
--The regular place for iSCSI database files: /etc/iscsi/nodes
-+The regular place for iSCSI database files: /var/lib/iscsi/nodes
- 
- The iscsiadm utility is a command-line tool to manage (update, delete,
- insert, query) the persistent database.
-@@ -422,7 +422,7 @@ a scsi_host per HBA port).
+From d77d9e1ffb1775c3602d8cc9ae56c701aa7c476a Mon Sep 17 00:00:00 2001
+From: Chris Leech <cleech at redhat.com>
+Date: Mon, 19 Nov 2012 16:38:45 -0800
+Subject: use var for config
+
+---
+ README         | 33 ++++++++++++++++-----------------
+ doc/iscsiadm.8 |  8 ++++----
+ usr/idbm.c     |  6 +++---
+ usr/idbm.h     | 15 +++++++++------
+ usr/iface.h    |  4 +++-
+ 5 files changed, 35 insertions(+), 31 deletions(-)
+
+diff --git a/README b/README
+index 2a8319a..e5ae2c1 100644
+--- a/README
++++ b/README
+@@ -156,8 +156,7 @@ Usage: iscsid [OPTION]
+ 
+ Open-iSCSI persistent configuration is stored in a number of
+ directories under a configuration root directory, using a flat-file
+-format. This configuration root directory is /etc/iscsi by default,
+-but may also commonly be in /var/lib/iscsi.
++format. This configuration root directory is /var/lib/iscsi by default.
+ 
+ Configuration is contained in directories for:
+ 
+@@ -444,7 +443,7 @@ a scsi_host per HBA port).
  To manage both types of initiator stacks, iscsiadm uses the interface (iface)
  structure. For each HBA port or for software iscsi for each network
  device (ethX) or NIC, that you wish to bind sessions to you must create
@@ -58,7 +34,7 @@ diff -aurp open-iscsi-2.0-872-rc4-bnx2i.base/README open-iscsi-2.0-872-rc4-bnx2i
  
  Prep:
  
-@@ -456,29 +456,29 @@ Running:
+@@ -478,29 +477,29 @@ Running:
  iface0 qla4xxx,00:c0:dd:08:63:e8,20.15.0.7,default,iqn.2005-06.com.redhat:madmax
  iface1 qla4xxx,00:c0:dd:08:63:ea,20.15.0.9,default,iqn.2005-06.com.redhat:madmax
  
@@ -93,7 +69,7 @@ diff -aurp open-iscsi-2.0-872-rc4-bnx2i.base/README open-iscsi-2.0-872-rc4-bnx2i
  
  iface.transport_name = tcp
  iface.hwaddress = 00:C0:DD:08:63:E7
-@@ -528,7 +528,7 @@ cxgb3i.00:07:43:05:97:07 cxgb3i,00:07:43
+@@ -550,7 +549,7 @@ cxgb3i.00:07:43:05:97:07 cxgb3i,00:07:43:05:97:07,<empty>,<empty>,<empty>
  qla4xxx.00:0e:1e:04:8b:2e qla4xxx,00:0e:1e:04:8b:2e,<empty>,<empty>,<empty>
  
  
@@ -102,7 +78,7 @@ diff -aurp open-iscsi-2.0-872-rc4-bnx2i.base/README open-iscsi-2.0-872-rc4-bnx2i
  The format is:
  
  iface_name transport_name,hwaddress,ipaddress,net_ifacename,initiatorname
-@@ -614,7 +614,7 @@ need a seperate network connection to th
+@@ -636,7 +635,7 @@ need a seperate network connection to the target for discovery purposes.
  *This will be fixed in the next version of open-iscsi*
  
  For compatibility reasons, when you run iscsiadm to do discovery, it
@@ -111,7 +87,7 @@ diff -aurp open-iscsi-2.0-872-rc4-bnx2i.base/README open-iscsi-2.0-872-rc4-bnx2i
  tcp for the iface.transport and it will bind the portals that are discovered
  so that they will be logged in through those ifaces. This behavior can also
  be overriden by passing in the interfaces you want to use. For the case
-@@ -632,7 +632,7 @@ we do not bind a session to a iface, the
+@@ -654,7 +653,7 @@ we do not bind a session to a iface, then you can use the special iface
  
  iscsiadm -m discoverydb -t st -p ip:port -I default --discover -P 1
  
@@ -120,7 +96,7 @@ diff -aurp open-iscsi-2.0-872-rc4-bnx2i.base/README open-iscsi-2.0-872-rc4-bnx2i
  not pass anything into iscsiadm, running iscsiadm will do the default
  behavior, where we allow the network subsystem to decide which
  device to use.
-@@ -674,7 +674,7 @@ To now log into targets it is the same a
+@@ -696,7 +695,7 @@ To now log into targets it is the same as with sofware iscsi. See section
  
  	    ./iscsiadm -m discoverydb -t st -p 192.168.1.1:3260 --discover
  
@@ -129,7 +105,7 @@ diff -aurp open-iscsi-2.0-872-rc4-bnx2i.base/README open-iscsi-2.0-872-rc4-bnx2i
  	ID [portal = 192.168.1.1:3260 and type = sendtargets. If found it
  	will perform discovery using the settings stored in the record.
  	If a record does not exist, it will be created using the iscsid.conf
-@@ -683,7 +683,7 @@ To now log into targets it is the same a
+@@ -705,7 +704,7 @@ To now log into targets it is the same as with sofware iscsi. See section
  	The argument to -p may also be a hostname instead of an address.
  	    ./iscsiadm -m discoverydb -t st -p smoehost --discover
  
@@ -138,7 +114,7 @@ diff -aurp open-iscsi-2.0-872-rc4-bnx2i.base/README open-iscsi-2.0-872-rc4-bnx2i
  	interfaces using software iscsi. If any are found then nodes found
  	during discovery will be setup so that they can logged in through
  	those interfaces. To specify a specific iface, pass the
-@@ -739,7 +739,7 @@ To now log into targets it is the same a
+@@ -761,7 +760,7 @@ To now log into targets it is the same as with sofware iscsi. See section
  	This command will perform discovery, but not manipulate the node DB.
  
    - SendTargets iSCSI Discovery with a specific interface. If you
@@ -147,7 +123,7 @@ diff -aurp open-iscsi-2.0-872-rc4-bnx2i.base/README open-iscsi-2.0-872-rc4-bnx2i
  	then you can pass them in during discovery:
  
  	     ./iscsiadm -m discoverydb -t sendtargets -p 192.168.1.1:3260 \
-@@ -1050,8 +1050,8 @@ where targetname is the name of the targ
+@@ -1072,8 +1071,8 @@ where targetname is the name of the target and ip_address:port is the address
  and port of the portal. tpgt, is the portal group tag of
  the portal, and is not used in iscsiadm commands except for static
  record creation. And iface name is the name of the iscsi interface
@@ -158,7 +134,7 @@ diff -aurp open-iscsi-2.0-872-rc4-bnx2i.base/README open-iscsi-2.0-872-rc4-bnx2i
  Default here is iscsi_tcp/tcp to be used over which ever NIC the
  network layer decides is best.
  
-@@ -1166,7 +1166,7 @@ If set, iscsid will perform discovery to
+@@ -1188,7 +1187,7 @@ If set, iscsid will perform discovery to the address every
  discovery.isns.discoveryd_poll_inval or
  discovery.sendtargets.discoveryd_poll_inval seconds,
  and it will log into any portals found from the discovery source using
@@ -167,10 +143,46 @@ diff -aurp open-iscsi-2.0-872-rc4-bnx2i.base/README open-iscsi-2.0-872-rc4-bnx2i
  
  Note that for iSNS the poll_interval does not have to be set. If not set,
  iscsid will only perform rediscovery when it gets a SCN from the server.
-diff -aurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/idbm.c open-iscsi-2.0-872-rc4-bnx2i.build/usr/idbm.c
---- open-iscsi-2.0-872-rc4-bnx2i.base/usr/idbm.c	2011-08-14 16:41:23.000000000 -0500
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/usr/idbm.c	2011-08-14 16:41:07.000000000 -0500
-@@ -2359,9 +2359,9 @@ free_info:
+diff --git a/doc/iscsiadm.8 b/doc/iscsiadm.8
+index 7c209f6..e94cca0 100644
+--- a/doc/iscsiadm.8
++++ b/doc/iscsiadm.8
+@@ -89,7 +89,7 @@ This option is only valid for ping submode.
+ .TP
+ \fB\-I\fR, \fB\-\-interface=\fI[iface]\fR
+ The interface argument specifies the iSCSI interface to use for the operation.
+-iSCSI interfaces (iface) are defined in /etc/iscsi/ifaces. For hardware
++iSCSI interfaces (iface) are defined in /var/lib/iscsi/ifaces. For hardware
+ iSCSI (qla4xxx) the iface config must have the hardware address
+ (iface.hwaddress = port's MAC address)
+ and the driver/transport_name (iface.transport_name). The iface's name is
+@@ -166,7 +166,7 @@ If no other options are specified: for \fIdiscoverydb\fR and \fInode\fR, all
+ of their respective records are displayed; for \fIsession\fR, all active
+ sessions and connections are displayed; for \fIfw\fR, all boot firmware
+ values are displayed; for \fIhost\fR, all iSCSI hosts are displayed; and
+-for \fIiface\fR, all ifaces setup in /etc/iscsi/ifaces are displayed.
++for \fIiface\fR, all ifaces setup in /var/lib/iscsi/ifaces are displayed.
+ 
+ .TP
+ \fB\-n\fR, \fB\-\-name=\fIname\fR
+@@ -535,10 +535,10 @@ The configuration file read by \fBiscsid\fR and \fBiscsiadm\fR on startup.
+ The file containing the iSCSI InitiatorName and InitiatorAlias read by
+ \fBiscsid\fR and \fBiscsiadm\fR on startup.
+ .TP
+-/etc/iscsi/nodes/
++/var/lib/iscsi/nodes/
+ This directory contains the nodes with their targets.
+ .TP
+-/etc/iscsi/send_targets
++/var/lib/iscsi/send_targets
+ This directory contains the portals.
+ 
+ .SH "SEE ALSO"
+diff --git a/usr/idbm.c b/usr/idbm.c
+index a1d7d37..806d90e 100644
+--- a/usr/idbm.c
++++ b/usr/idbm.c
+@@ -2472,9 +2472,9 @@ free_info:
  int idbm_init(idbm_get_config_file_fn *fn)
  {
  	/* make sure root db dir is there */
@@ -183,12 +195,13 @@ diff -aurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/idbm.c open-iscsi-2.0-872-rc4-b
  				   errno);
  			return errno;
  		}
-diff -aurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/idbm.h open-iscsi-2.0-872-rc4-bnx2i.build/usr/idbm.h
---- open-iscsi-2.0-872-rc4-bnx2i.base/usr/idbm.h	2011-08-14 16:33:53.000000000 -0500
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/usr/idbm.h	2011-08-14 16:41:07.000000000 -0500
-@@ -27,12 +27,15 @@
- #include "initiator.h"
+diff --git a/usr/idbm.h b/usr/idbm.h
+index 245f046..5d81df7 100644
+--- a/usr/idbm.h
++++ b/usr/idbm.h
+@@ -28,12 +28,15 @@
  #include "config.h"
+ #include "list.h"
  
 -#define NODE_CONFIG_DIR		ISCSI_CONFIG_ROOT"nodes"
 -#define SLP_CONFIG_DIR		ISCSI_CONFIG_ROOT"slp"
@@ -208,9 +221,10 @@ diff -aurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/idbm.h open-iscsi-2.0-872-rc4-b
  #define ST_CONFIG_NAME		"st_config"
  #define ISNS_CONFIG_NAME	"isns_config"
  
-diff -aurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/iface.h open-iscsi-2.0-872-rc4-bnx2i.build/usr/iface.h
---- open-iscsi-2.0-872-rc4-bnx2i.base/usr/iface.h	2011-08-14 16:33:53.000000000 -0500
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/usr/iface.h	2011-08-14 16:41:07.000000000 -0500
+diff --git a/usr/iface.h b/usr/iface.h
+index 01f7074..f396918 100644
+--- a/usr/iface.h
++++ b/usr/iface.h
 @@ -20,7 +20,9 @@
  #ifndef ISCSI_IFACE_H
  #define ISCSI_IFACE_H
@@ -222,3 +236,6 @@ diff -aurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/iface.h open-iscsi-2.0-872-rc4-
  
  struct iface_rec;
  struct list_head;
+-- 
+1.7.11.7
+
diff --git a/0053-use-red-hat-for-name.patch b/0053-use-red-hat-for-name.patch
new file mode 100644
index 0000000..9d36619
--- /dev/null
+++ b/0053-use-red-hat-for-name.patch
@@ -0,0 +1,25 @@
+From 88d864140cacdc1727091ee0ce61fcbd90cae472 Mon Sep 17 00:00:00 2001
+From: Chris Leech <cleech at redhat.com>
+Date: Mon, 19 Nov 2012 16:40:04 -0800
+Subject: use red hat for name
+
+---
+ utils/iscsi-iname.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/utils/iscsi-iname.c b/utils/iscsi-iname.c
+index 6347edc..cb2f6c8 100644
+--- a/utils/iscsi-iname.c
++++ b/utils/iscsi-iname.c
+@@ -73,7 +73,7 @@ main(int argc, char *argv[])
+ 			exit(0);
+ 		}
+ 	} else {
+-		prefix = "iqn.2005-03.org.open-iscsi";
++		prefix = "iqn.1994-05.com.redhat";
+ 	}
+ 
+ 	/* try to feed some entropy from the pool to MD5 in order to get
+-- 
+1.7.11.7
+
diff --git a/iscsi-initiator-utils-add-libiscsi.patch b/0054-add-libiscsi.patch
similarity index 94%
rename from iscsi-initiator-utils-add-libiscsi.patch
rename to 0054-add-libiscsi.patch
index 4b0e16e..9eb9c6c 100644
--- a/iscsi-initiator-utils-add-libiscsi.patch
+++ b/0054-add-libiscsi.patch
@@ -1,7 +1,140 @@
-diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/libiscsi.c open-iscsi-2.0-872-rc4-bnx2i.build/libiscsi/libiscsi.c
---- open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/libiscsi.c	1969-12-31 18:00:00.000000000 -0600
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/libiscsi/libiscsi.c	2011-08-14 16:53:58.000000000 -0500
-@@ -0,0 +1,612 @@
+From 8f94617e1b332031b01a0363a6757bfb5a039d89 Mon Sep 17 00:00:00 2001
+From: Chris Leech <cleech at redhat.com>
+Date: Mon, 19 Nov 2012 16:43:15 -0800
+Subject: add libiscsi
+
+---
+ Makefile                                    |    2 +
+ libiscsi/Makefile                           |   61 ++
+ libiscsi/libiscsi.c                         |  620 +++++++++++
+ libiscsi/libiscsi.doxy                      | 1473 +++++++++++++++++++++++++++
+ libiscsi/libiscsi.h                         |  344 +++++++
+ libiscsi/pylibiscsi.c                       |  638 ++++++++++++
+ libiscsi/setup.py                           |    9 +
+ libiscsi/tests/test_discovery_firmware.c    |   53 +
+ libiscsi/tests/test_discovery_sendtargets.c |   60 ++
+ libiscsi/tests/test_get_auth.c              |   70 ++
+ libiscsi/tests/test_get_initiator_name.c    |   38 +
+ libiscsi/tests/test_get_network_config.c    |   45 +
+ libiscsi/tests/test_login.c                 |   52 +
+ libiscsi/tests/test_logout.c                |   51 +
+ libiscsi/tests/test_params.c                |  103 ++
+ libiscsi/tests/test_set_auth.c              |   58 ++
+ usr/Makefile                                |    2 +-
+ usr/discovery.c                             |    5 +
+ usr/idbm.c                                  |    6 +-
+ usr/idbm.h                                  |    3 +
+ usr/iscsi_ipc.h                             |    2 +
+ 21 files changed, 3691 insertions(+), 4 deletions(-)
+ create mode 100644 libiscsi/Makefile
+ create mode 100644 libiscsi/libiscsi.c
+ create mode 100644 libiscsi/libiscsi.doxy
+ create mode 100644 libiscsi/libiscsi.h
+ create mode 100644 libiscsi/pylibiscsi.c
+ create mode 100644 libiscsi/setup.py
+ create mode 100644 libiscsi/tests/test_discovery_firmware.c
+ create mode 100644 libiscsi/tests/test_discovery_sendtargets.c
+ create mode 100644 libiscsi/tests/test_get_auth.c
+ create mode 100644 libiscsi/tests/test_get_initiator_name.c
+ create mode 100644 libiscsi/tests/test_get_network_config.c
+ create mode 100644 libiscsi/tests/test_login.c
+ create mode 100644 libiscsi/tests/test_logout.c
+ create mode 100644 libiscsi/tests/test_params.c
+ create mode 100644 libiscsi/tests/test_set_auth.c
+
+diff --git a/Makefile b/Makefile
+index c5d9700..6dfbde3 100644
+--- a/Makefile
++++ b/Makefile
+@@ -32,6 +32,7 @@ user: utils/open-isns/Makefile
+ 	$(MAKE) -C utils/fwparam_ibft
+ 	$(MAKE) -C usr
+ 	$(MAKE) -C utils
++	$(MAKE) -C libiscsi
+ 	@echo
+ 	@echo "Compilation complete                 Output file"
+ 	@echo "-----------------------------------  ----------------"
+@@ -56,6 +57,7 @@ kernel: force
+ force: ;
+ 
+ clean:
++	$(MAKE) -C libiscsi clean
+ 	$(MAKE) -C utils/sysdeps clean
+ 	$(MAKE) -C utils/fwparam_ibft clean
+ 	$(MAKE) -C utils clean
+diff --git a/libiscsi/Makefile b/libiscsi/Makefile
+new file mode 100644
+index 0000000..317a7ec
+--- /dev/null
++++ b/libiscsi/Makefile
+@@ -0,0 +1,61 @@
++# This Makefile will work only with GNU make.
++
++OSNAME=$(shell uname -s)
++OPTFLAGS ?= -O2 -g
++WARNFLAGS ?= -Wall -Wstrict-prototypes
++CFLAGS = $(OPTFLAGS) $(WARNFLAGS) -I../include -I../usr \
++		-D$(OSNAME) -fPIC -D_GNU_SOURCE -fvisibility=hidden
++LIB = libiscsi.so.0
++TESTS = tests/test_discovery_sendtargets tests/test_discovery_firmware
++TESTS += tests/test_login tests/test_logout tests/test_params
++TESTS += tests/test_get_network_config tests/test_get_initiator_name
++TESTS += tests/test_set_auth tests/test_get_auth
++
++COMMON_SRCS = sysdeps.o
++# sources shared between iscsid, iscsiadm and iscsistart
++ISCSI_LIB_SRCS = netlink.o transport.o cxgbi.o be2iscsi.o iscsi_timer.o initiator_common.o iscsi_err.o session_info.o iscsi_util.o io.o auth.o discovery.o login.o log.o md5.o sha1.o iface.o idbm.o sysfs.o iscsi_sysfs.o iscsi_net_util.o iscsid_req.o iser.o uip_mgmt_ipc.o
++FW_PARAM_SRCS = fw_entry.o prom_lex.o prom_parse.tab.o fwparam_ppc.o fwparam_sysfs.o
++
++# sources shared with the userspace utils, note we build these separately
++# to get PIC versions.
++COMMON_OBJS = $(patsubst %.o, common-objs/%.o, $(COMMON_SRCS))
++USR_OBJS = $(patsubst %.o, usr-objs/%.o, $(ISCSI_LIB_SRCS) strings.o)
++FW_OBJS = $(patsubst %.o, fw-objs/%.o, $(FW_PARAM_SRCS))
++
++# Flags for the tests
++tests/% : CFLAGS = $(OPTFLAGS) $(WARNFLAGS) -I.
++
++all: lib tests html
++
++lib: $(LIB)
++tests: $(TESTS)
++
++common-objs/%.o: ../utils/sysdeps/%.c
++	mkdir -p common-objs
++	$(CC) $(CFLAGS) -c $< -o $@
++
++usr-objs/%.o: ../usr/%.c
++	mkdir -p usr-objs
++	$(CC) $(CFLAGS) -c $< -o $@
++
++fw-objs/%.o: ../utils/fwparam_ibft/%.c
++	mkdir -p fw-objs
++	$(CC) $(CFLAGS) -c $< -o $@
++
++$(LIB): $(COMMON_OBJS) $(FW_OBJS) $(USR_OBJS) libiscsi.o
++	$(CC) $(CFLAGS) -shared -Wl,-soname,$(LIB) $^ -o $@
++	ln -s -f $(LIB) libiscsi.so
++
++$(TESTS): $(FW_OBJS) $(COMMON_OBJS) $(USR_OBJS) $(LIB)
++
++html: libiscsi.h libiscsi.doxy
++	doxygen libiscsi.doxy
++
++clean:
++	rm -rf *.o common-objs usr-objs fw-objs libuip-objs libiscsi.so* \
++			.depend *~ html $(TESTS) tests/*~
++
++depend:
++	gcc $(CFLAGS) -M `ls *.c` > .depend
++
++-include .depend ../usr/.depend
+diff --git a/libiscsi/libiscsi.c b/libiscsi/libiscsi.c
+new file mode 100644
+index 0000000..2a176e8
+--- /dev/null
++++ b/libiscsi/libiscsi.c
+@@ -0,0 +1,620 @@
 +/*
 + * iSCSI Administration library
 + *
@@ -478,18 +611,26 @@ diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/libiscsi.c open-iscsi-2.0
 +	const char *parameter, const char *value)
 +{
 +	int nr_found = 0, rc;
-+	struct db_set_param set_param = {
-+		.name = (char *)parameter,
-+		.value = (char *)value,
-+	};
++	struct user_param *param;
++	struct list_head params;
++
++	INIT_LIST_HEAD(&params);
++	param = idbm_alloc_user_param(parameter, value);
++	if (!param) {
++		rc = ENOMEM;
++		goto leave;
++	}
++	list_add_tail(&params, &param->list);
 +
-+	CHECK(idbm_for_each_iface(&nr_found, &set_param, idbm_node_set_param,
++	CHECK(idbm_for_each_iface(&nr_found, &params, idbm_node_set_param,
 +		(char *)node->name, node->tpgt,
 +		(char *)node->address, node->port))
 +	if (nr_found == 0) {
 +		strcpy(context->error_str, "No such node");
 +		rc = ENODEV;
 +	}
++	free(param->name);
++	free(param);
 +leave:
 +	return rc;
 +}
@@ -614,9 +755,11 @@ diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/libiscsi.c open-iscsi-2.0
 +
 +	return 0;
 +}
-diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/libiscsi.doxy open-iscsi-2.0-872-rc4-bnx2i.build/libiscsi/libiscsi.doxy
---- open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/libiscsi.doxy	1969-12-31 18:00:00.000000000 -0600
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/libiscsi/libiscsi.doxy	2011-08-14 16:46:24.000000000 -0500
+diff --git a/libiscsi/libiscsi.doxy b/libiscsi/libiscsi.doxy
+new file mode 100644
+index 0000000..663770f
+--- /dev/null
++++ b/libiscsi/libiscsi.doxy
 @@ -0,0 +1,1473 @@
 +# Doxyfile 1.5.7.1
 +
@@ -2091,9 +2234,11 @@ diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/libiscsi.doxy open-iscsi-
 +# used. If set to NO the values of all tags below this one will be ignored.
 +
 +SEARCHENGINE           = NO
-diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/libiscsi.h open-iscsi-2.0-872-rc4-bnx2i.build/libiscsi/libiscsi.h
---- open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/libiscsi.h	1969-12-31 18:00:00.000000000 -0600
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/libiscsi/libiscsi.h	2011-08-14 16:53:58.000000000 -0500
+diff --git a/libiscsi/libiscsi.h b/libiscsi/libiscsi.h
+new file mode 100644
+index 0000000..756590e
+--- /dev/null
++++ b/libiscsi/libiscsi.h
 @@ -0,0 +1,344 @@
 +/*
 + * iSCSI Administration library
@@ -2439,74 +2584,11 @@ diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/libiscsi.h open-iscsi-2.0
 +#endif /* __cplusplus */
 +
 +#endif
-diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/Makefile open-iscsi-2.0-872-rc4-bnx2i.build/libiscsi/Makefile
---- open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/Makefile	1969-12-31 18:00:00.000000000 -0600
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/libiscsi/Makefile	2011-08-14 16:46:24.000000000 -0500
-@@ -0,0 +1,61 @@
-+# This Makefile will work only with GNU make.
-+
-+OSNAME=$(shell uname -s)
-+OPTFLAGS ?= -O2 -g
-+WARNFLAGS ?= -Wall -Wstrict-prototypes
-+CFLAGS = $(OPTFLAGS) $(WARNFLAGS) -I../include -I../usr \
-+		-D$(OSNAME) -fPIC -D_GNU_SOURCE -fvisibility=hidden
-+LIB = libiscsi.so.0
-+TESTS = tests/test_discovery_sendtargets tests/test_discovery_firmware
-+TESTS += tests/test_login tests/test_logout tests/test_params
-+TESTS += tests/test_get_network_config tests/test_get_initiator_name
-+TESTS += tests/test_set_auth tests/test_get_auth
-+
-+COMMON_SRCS = sysdeps.o
-+# sources shared between iscsid, iscsiadm and iscsistart
-+ISCSI_LIB_SRCS = netlink.o transport.o cxgbi.o be2iscsi.o iscsi_timer.o initiator_common.o iscsi_err.o session_info.o iscsi_util.o dcb_app.o io.o auth.o discovery.o login.o log.o md5.o sha1.o iface.o idbm.o sysfs.o iscsi_sysfs.o iscsi_net_util.o iscsid_req.o
-+FW_PARAM_SRCS = fw_entry.o prom_lex.o prom_parse.tab.o fwparam_ppc.o fwparam_sysfs.o
-+
-+# sources shared with the userspace utils, note we build these separately
-+# to get PIC versions.
-+COMMON_OBJS = $(patsubst %.o, common-objs/%.o, $(COMMON_SRCS))
-+USR_OBJS = $(patsubst %.o, usr-objs/%.o, $(ISCSI_LIB_SRCS) strings.o)
-+FW_OBJS = $(patsubst %.o, fw-objs/%.o, $(FW_PARAM_SRCS))
-+
-+# Flags for the tests
-+tests/% : CFLAGS = $(OPTFLAGS) $(WARNFLAGS) -I.
-+
-+all: lib tests html
-+
-+lib: $(LIB)
-+tests: $(TESTS)
-+
-+common-objs/%.o: ../utils/sysdeps/%.c
-+	mkdir -p common-objs
-+	$(CC) $(CFLAGS) -c $< -o $@
-+
-+usr-objs/%.o: ../usr/%.c
-+	mkdir -p usr-objs
-+	$(CC) $(CFLAGS) -c $< -o $@
-+
-+fw-objs/%.o: ../utils/fwparam_ibft/%.c
-+	mkdir -p fw-objs
-+	$(CC) $(CFLAGS) -c $< -o $@
-+
-+$(LIB): $(COMMON_OBJS) $(FW_OBJS) $(USR_OBJS) libiscsi.o
-+	$(CC) $(CFLAGS) -shared -Wl,-soname,$(LIB) $^ -o $@
-+	ln -s -f $(LIB) libiscsi.so
-+
-+$(TESTS): $(FW_OBJS) $(COMMON_OBJS) $(USR_OBJS) $(LIB)
-+
-+html: libiscsi.h libiscsi.doxy
-+	doxygen libiscsi.doxy
-+
-+clean:
-+	rm -rf *.o common-objs usr-objs fw-objs libuip-objs libiscsi.so* \
-+			.depend *~ html $(TESTS) tests/*~
-+
-+depend:
-+	gcc $(CFLAGS) -M `ls *.c` > .depend
-+
-+-include .depend ../usr/.depend
-diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/pylibiscsi.c open-iscsi-2.0-872-rc4-bnx2i.build/libiscsi/pylibiscsi.c
---- open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/pylibiscsi.c	1969-12-31 18:00:00.000000000 -0600
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/libiscsi/pylibiscsi.c	2011-08-14 16:53:58.000000000 -0500
+diff --git a/libiscsi/pylibiscsi.c b/libiscsi/pylibiscsi.c
+new file mode 100644
+index 0000000..4b09aa7
+--- /dev/null
++++ b/libiscsi/pylibiscsi.c
 @@ -0,0 +1,638 @@
 +/*
 + * iSCSI Administration library
@@ -3146,9 +3228,11 @@ diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/pylibiscsi.c open-iscsi-2
 +	Py_INCREF(&PyIscsiNode_Type);
 +	PyModule_AddObject(m, "node", (PyObject *) &PyIscsiNode_Type);
 +}
-diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/setup.py open-iscsi-2.0-872-rc4-bnx2i.build/libiscsi/setup.py
---- open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/setup.py	1969-12-31 18:00:00.000000000 -0600
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/libiscsi/setup.py	2011-08-14 16:46:24.000000000 -0500
+diff --git a/libiscsi/setup.py b/libiscsi/setup.py
+new file mode 100644
+index 0000000..bb4329b
+--- /dev/null
++++ b/libiscsi/setup.py
 @@ -0,0 +1,9 @@
 +from distutils.core import setup, Extension
 +
@@ -3159,9 +3243,11 @@ diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/setup.py open-iscsi-2.0-8
 +
 +setup (name = 'PyIscsi',version = '1.0',
 +       description = 'libiscsi python bindings', ext_modules = [module1])
-diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/tests/test_discovery_firmware.c open-iscsi-2.0-872-rc4-bnx2i.build/libiscsi/tests/test_discovery_firmware.c
---- open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/tests/test_discovery_firmware.c	1969-12-31 18:00:00.000000000 -0600
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/libiscsi/tests/test_discovery_firmware.c	2011-08-14 16:46:24.000000000 -0500
+diff --git a/libiscsi/tests/test_discovery_firmware.c b/libiscsi/tests/test_discovery_firmware.c
+new file mode 100644
+index 0000000..76e852a
+--- /dev/null
++++ b/libiscsi/tests/test_discovery_firmware.c
 @@ -0,0 +1,53 @@
 +/*
 + * iSCSI Administration library
@@ -3216,9 +3302,11 @@ diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/tests/test_discovery_firm
 +
 +	return rc;
 +}
-diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/tests/test_discovery_sendtargets.c open-iscsi-2.0-872-rc4-bnx2i.build/libiscsi/tests/test_discovery_sendtargets.c
---- open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/tests/test_discovery_sendtargets.c	1969-12-31 18:00:00.000000000 -0600
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/libiscsi/tests/test_discovery_sendtargets.c	2011-08-14 16:46:24.000000000 -0500
+diff --git a/libiscsi/tests/test_discovery_sendtargets.c b/libiscsi/tests/test_discovery_sendtargets.c
+new file mode 100644
+index 0000000..1a3c12e
+--- /dev/null
++++ b/libiscsi/tests/test_discovery_sendtargets.c
 @@ -0,0 +1,60 @@
 +/*
 + * iSCSI Administration library
@@ -3280,9 +3368,11 @@ diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/tests/test_discovery_send
 +
 +	return rc;
 +}
-diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/tests/test_get_auth.c open-iscsi-2.0-872-rc4-bnx2i.build/libiscsi/tests/test_get_auth.c
---- open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/tests/test_get_auth.c	1969-12-31 18:00:00.000000000 -0600
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/libiscsi/tests/test_get_auth.c	2011-08-14 16:46:24.000000000 -0500
+diff --git a/libiscsi/tests/test_get_auth.c b/libiscsi/tests/test_get_auth.c
+new file mode 100644
+index 0000000..5e234da
+--- /dev/null
++++ b/libiscsi/tests/test_get_auth.c
 @@ -0,0 +1,70 @@
 +/*
 + * iSCSI Administration library
@@ -3354,9 +3444,11 @@ diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/tests/test_get_auth.c ope
 +
 +	return rc;
 +}
-diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/tests/test_get_initiator_name.c open-iscsi-2.0-872-rc4-bnx2i.build/libiscsi/tests/test_get_initiator_name.c
---- open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/tests/test_get_initiator_name.c	1969-12-31 18:00:00.000000000 -0600
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/libiscsi/tests/test_get_initiator_name.c	2011-08-14 16:46:24.000000000 -0500
+diff --git a/libiscsi/tests/test_get_initiator_name.c b/libiscsi/tests/test_get_initiator_name.c
+new file mode 100644
+index 0000000..997c053
+--- /dev/null
++++ b/libiscsi/tests/test_get_initiator_name.c
 @@ -0,0 +1,38 @@
 +/*
 + * iSCSI Administration library
@@ -3396,9 +3488,11 @@ diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/tests/test_get_initiator_
 +
 +	return 0;
 +}
-diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/tests/test_get_network_config.c open-iscsi-2.0-872-rc4-bnx2i.build/libiscsi/tests/test_get_network_config.c
---- open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/tests/test_get_network_config.c	1969-12-31 18:00:00.000000000 -0600
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/libiscsi/tests/test_get_network_config.c	2011-08-14 16:46:24.000000000 -0500
+diff --git a/libiscsi/tests/test_get_network_config.c b/libiscsi/tests/test_get_network_config.c
+new file mode 100644
+index 0000000..2dedd61
+--- /dev/null
++++ b/libiscsi/tests/test_get_network_config.c
 @@ -0,0 +1,45 @@
 +/*
 + * iSCSI Administration library
@@ -3445,9 +3539,11 @@ diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/tests/test_get_network_co
 +
 +	return 0;
 +}
-diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/tests/test_login.c open-iscsi-2.0-872-rc4-bnx2i.build/libiscsi/tests/test_login.c
---- open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/tests/test_login.c	1969-12-31 18:00:00.000000000 -0600
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/libiscsi/tests/test_login.c	2011-08-14 16:46:24.000000000 -0500
+diff --git a/libiscsi/tests/test_login.c b/libiscsi/tests/test_login.c
+new file mode 100644
+index 0000000..3eb70d6
+--- /dev/null
++++ b/libiscsi/tests/test_login.c
 @@ -0,0 +1,52 @@
 +/*
 + * iSCSI Administration library
@@ -3501,9 +3597,11 @@ diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/tests/test_login.c open-i
 +
 +	return rc;
 +}
-diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/tests/test_logout.c open-iscsi-2.0-872-rc4-bnx2i.build/libiscsi/tests/test_logout.c
---- open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/tests/test_logout.c	1969-12-31 18:00:00.000000000 -0600
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/libiscsi/tests/test_logout.c	2011-08-14 16:46:24.000000000 -0500
+diff --git a/libiscsi/tests/test_logout.c b/libiscsi/tests/test_logout.c
+new file mode 100644
+index 0000000..b734dca
+--- /dev/null
++++ b/libiscsi/tests/test_logout.c
 @@ -0,0 +1,51 @@
 +/*
 + * iSCSI Administration library
@@ -3556,9 +3654,11 @@ diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/tests/test_logout.c open-
 +
 +	return rc;
 +}
-diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/tests/test_params.c open-iscsi-2.0-872-rc4-bnx2i.build/libiscsi/tests/test_params.c
---- open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/tests/test_params.c	1969-12-31 18:00:00.000000000 -0600
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/libiscsi/tests/test_params.c	2011-08-14 16:46:24.000000000 -0500
+diff --git a/libiscsi/tests/test_params.c b/libiscsi/tests/test_params.c
+new file mode 100644
+index 0000000..d3223be
+--- /dev/null
++++ b/libiscsi/tests/test_params.c
 @@ -0,0 +1,103 @@
 +/*
 + * iSCSI Administration library
@@ -3663,9 +3763,11 @@ diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/tests/test_params.c open-
 +
 +	return rc;
 +}
-diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/tests/test_set_auth.c open-iscsi-2.0-872-rc4-bnx2i.build/libiscsi/tests/test_set_auth.c
---- open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/tests/test_set_auth.c	1969-12-31 18:00:00.000000000 -0600
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/libiscsi/tests/test_set_auth.c	2011-08-14 16:46:24.000000000 -0500
+diff --git a/libiscsi/tests/test_set_auth.c b/libiscsi/tests/test_set_auth.c
+new file mode 100644
+index 0000000..a21f888
+--- /dev/null
++++ b/libiscsi/tests/test_set_auth.c
 @@ -0,0 +1,58 @@
 +/*
 + * iSCSI Administration library
@@ -3725,28 +3827,23 @@ diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/tests/test_set_auth.c ope
 +
 +	return rc;
 +}
-diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/Makefile open-iscsi-2.0-872-rc4-bnx2i.build/Makefile
---- open-iscsi-2.0-872-rc4-bnx2i.base/Makefile	2011-08-14 16:53:01.000000000 -0500
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/Makefile	2011-08-14 16:46:24.000000000 -0500
-@@ -32,6 +32,7 @@ user: ;
- 	$(MAKE) -C utils/fwparam_ibft
- 	$(MAKE) -C usr
- 	$(MAKE) -C utils
-+	$(MAKE) -C libiscsi
- 	@echo
- 	@echo "Compilation complete                 Output file"
- 	@echo "-----------------------------------  ----------------"
-@@ -53,6 +54,7 @@ kernel: force
- force: ;
+diff --git a/usr/Makefile b/usr/Makefile
+index 1506111..015f1b9 100644
+--- a/usr/Makefile
++++ b/usr/Makefile
+@@ -31,7 +31,7 @@ endif
+ OPTFLAGS ?= -O2 -g
+ WARNFLAGS ?= -Wall -Wstrict-prototypes
+ CFLAGS += $(OPTFLAGS) $(WARNFLAGS) -I../include -I. -I../utils/open-isns \
+-				-D$(OSNAME) $(IPC_CFLAGS)
++				-D$(OSNAME) $(IPC_CFLAGS) -DISNS_ENABLE
+ PROGRAMS = iscsid iscsiadm iscsistart
  
- clean:
-+	$(MAKE) -C libiscsi clean
- 	$(MAKE) -C utils/sysdeps clean
- 	$(MAKE) -C utils/fwparam_ibft clean
- 	$(MAKE) -C utils clean
-diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/discovery.c open-iscsi-2.0-872-rc4-bnx2i.build/usr/discovery.c
---- open-iscsi-2.0-872-rc4-bnx2i.base/usr/discovery.c	2011-08-14 16:53:01.000000000 -0500
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/usr/discovery.c	2011-08-14 16:46:24.000000000 -0500
+ # libc compat files
+diff --git a/usr/discovery.c b/usr/discovery.c
+index afce6c0..0c93749 100644
+--- a/usr/discovery.c
++++ b/usr/discovery.c
 @@ -36,6 +36,7 @@
  #include "types.h"
  #include "iscsi_proto.h"
@@ -3783,10 +3880,11 @@ diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/discovery.c open-iscsi-2.0-872
  
  int discovery_fw(void *data, struct iface_rec *iface,
  		 struct list_head *rec_list)
-diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/idbm.c open-iscsi-2.0-872-rc4-bnx2i.build/usr/idbm.c
---- open-iscsi-2.0-872-rc4-bnx2i.base/usr/idbm.c	2011-08-14 16:53:01.000000000 -0500
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/usr/idbm.c	2011-08-14 16:46:24.000000000 -0500
-@@ -1274,9 +1274,9 @@ int idbm_print_all_discovery(int info_le
+diff --git a/usr/idbm.c b/usr/idbm.c
+index 806d90e..c20f7d9 100644
+--- a/usr/idbm.c
++++ b/usr/idbm.c
+@@ -1335,9 +1335,9 @@ int idbm_print_all_discovery(int info_level)
   * fn should return -1 if it skipped the rec, a ISCSI_ERR error code if
   * the operation failed or 0 if fn was run successfully.
   */
@@ -3799,10 +3897,11 @@ diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/idbm.c open-iscsi-2.0-872-rc4-
  {
  	DIR *iface_dirfd;
  	struct dirent *iface_dent;
-diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/idbm.h open-iscsi-2.0-872-rc4-bnx2i.build/usr/idbm.h
---- open-iscsi-2.0-872-rc4-bnx2i.base/usr/idbm.h	2011-08-14 16:53:01.000000000 -0500
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/usr/idbm.h	2011-08-14 16:46:24.000000000 -0500
-@@ -98,6 +98,9 @@ struct rec_op_data {
+diff --git a/usr/idbm.h b/usr/idbm.h
+index 5d81df7..f645561 100644
+--- a/usr/idbm.h
++++ b/usr/idbm.h
+@@ -101,6 +101,9 @@ struct rec_op_data {
  	node_rec_t *match_rec;
  	idbm_iface_op_fn *fn;
  };
@@ -3812,25 +3911,17 @@ diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/idbm.h open-iscsi-2.0-872-rc4-
  extern int idbm_for_each_portal(int *found, void *data,
  				idbm_portal_op_fn *fn, char *targetname);
  extern int idbm_for_each_node(int *found, void *data,
-diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/iscsi_ipc.h open-iscsi-2.0-872-rc4-bnx2i.build/usr/iscsi_ipc.h
---- open-iscsi-2.0-872-rc4-bnx2i.base/usr/iscsi_ipc.h	2011-08-14 16:53:01.000000000 -0500
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/usr/iscsi_ipc.h	2011-08-14 16:46:24.000000000 -0500
-@@ -136,4 +136,6 @@ struct iscsi_ipc {
- 	int (*recv_conn_state) (struct iscsi_conn *conn, uint32_t *state);
+diff --git a/usr/iscsi_ipc.h b/usr/iscsi_ipc.h
+index db5f1f0..e0bf051 100644
+--- a/usr/iscsi_ipc.h
++++ b/usr/iscsi_ipc.h
+@@ -147,4 +147,6 @@ struct iscsi_ipc {
+ 			    uint16_t chap_tbl_idx);
  };
  
 +struct iscsi_ipc *ipc;
 +
  #endif /* ISCSI_IPC_H */
-diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/Makefile open-iscsi-2.0-872-rc4-bnx2i.build/usr/Makefile
---- open-iscsi-2.0-872-rc4-bnx2i.base/usr/Makefile	2011-08-14 16:53:01.000000000 -0500
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/usr/Makefile	2011-08-14 16:46:24.000000000 -0500
-@@ -33,7 +33,7 @@ endif
- OPTFLAGS ?= -O2 -g
- WARNFLAGS ?= -Wall -Wstrict-prototypes
- CFLAGS += $(OPTFLAGS) $(WARNFLAGS) -I../include -I. -I../utils/open-isns \
--					-D$(OSNAME) $(IPC_CFLAGS)
-+					-D$(OSNAME) $(IPC_CFLAGS) -DISNS_ENABLE
- PROGRAMS = iscsid iscsiadm iscsistart
- 
- # libc compat files
+-- 
+1.7.11.7
+
diff --git a/0055-dont-use-static.patch b/0055-dont-use-static.patch
new file mode 100644
index 0000000..c469e38
--- /dev/null
+++ b/0055-dont-use-static.patch
@@ -0,0 +1,25 @@
+From 82f3ef30850bb433725b60927969721bcca1df79 Mon Sep 17 00:00:00 2001
+From: Chris Leech <cleech at redhat.com>
+Date: Mon, 19 Nov 2012 17:04:29 -0800
+Subject: dont use static
+
+---
+ usr/Makefile | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/usr/Makefile b/usr/Makefile
+index 015f1b9..1669890 100644
+--- a/usr/Makefile
++++ b/usr/Makefile
+@@ -61,7 +61,7 @@ iscsiadm: $(ISCSI_LIB_SRCS) $(DISCOVERY_SRCS) iscsiadm.o session_mgmt.o
+ 
+ iscsistart: $(ISCSI_LIB_SRCS) $(INITIATOR_SRCS) $(FW_BOOT_SRCS) \
+ 		iscsistart.o statics.o
+-	$(CC) $(CFLAGS) -static $^ -o $@
++	$(CC) $(CFLAGS) $^ -o $@
+ clean:
+ 	rm -f *.o $(PROGRAMS) .depend $(LIBSYS)
+ 
+-- 
+1.7.11.7
+
diff --git a/0056-remove-the-offload-boot-supported-ifdef.patch b/0056-remove-the-offload-boot-supported-ifdef.patch
new file mode 100644
index 0000000..bdd2463
--- /dev/null
+++ b/0056-remove-the-offload-boot-supported-ifdef.patch
@@ -0,0 +1,45 @@
+From 55c5640e2571b3e4b8a1b33f0076971b5c865711 Mon Sep 17 00:00:00 2001
+From: Chris Leech <cleech at redhat.com>
+Date: Mon, 19 Nov 2012 17:09:24 -0800
+Subject: remove the offload boot supported ifdef
+
+---
+ usr/iface.c | 7 +------
+ 1 file changed, 1 insertion(+), 6 deletions(-)
+
+diff --git a/usr/iface.c b/usr/iface.c
+index c86892e..f5441c0 100644
+--- a/usr/iface.c
++++ b/usr/iface.c
+@@ -895,6 +895,7 @@ int iface_setup_from_boot_context(struct iface_rec *iface,
+ {
+ 	struct iscsi_transport *t = NULL;
+ 	uint32_t hostno;
++	int rc;
+ 
+ 	if (strlen(context->initiatorname))
+ 		strlcpy(iface->iname, context->initiatorname,
+@@ -907,10 +908,7 @@ int iface_setup_from_boot_context(struct iface_rec *iface,
+ 			return 0;
+ 		}
+ 	} else if (strlen(context->iface)) {
+-/* this ifdef is only temp until distros and firmwares are updated */
+-#ifdef OFFLOAD_BOOT_SUPPORTED
+ 		char transport_name[ISCSI_TRANSPORT_NAME_MAXLEN];
+-		int rc;
+ 
+ 		memset(transport_name, 0, ISCSI_TRANSPORT_NAME_MAXLEN);
+ 		/* make sure offload driver is loaded */
+@@ -936,9 +934,6 @@ int iface_setup_from_boot_context(struct iface_rec *iface,
+ 		}
+ 
+ 		strlcpy(iface->netdev, context->iface, sizeof(iface->netdev));
+-#else
+-		return 0;
+-#endif
+ 	} else
+ 		return 0;
+ 
+-- 
+1.7.11.7
+
diff --git a/iscsi-initiator-utils-uip-mgmt.patch b/0057-iscsid-iscsiuio-ipc-interface.patch
similarity index 68%
rename from iscsi-initiator-utils-uip-mgmt.patch
rename to 0057-iscsid-iscsiuio-ipc-interface.patch
index 8f81b16..98d1b45 100644
--- a/iscsi-initiator-utils-uip-mgmt.patch
+++ b/0057-iscsid-iscsiuio-ipc-interface.patch
@@ -1,30 +1,56 @@
-diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/include/iscsi_err.h open-iscsi-2.0-872-rc4-bnx2i.build/include/iscsi_err.h
---- open-iscsi-2.0-872-rc4-bnx2i.base/include/iscsi_err.h	2011-08-14 16:49:44.000000000 -0500
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/include/iscsi_err.h	2011-08-14 16:56:54.000000000 -0500
-@@ -58,6 +58,8 @@ enum {
- 	ISCSI_ERR_ISNS_QUERY		= 25,
- 	/* iSNS registration/deregistration failed */
- 	ISCSI_ERR_ISNS_REG_FAILED	= 26,
+From 5753a2f838fcb532ad56dc4c4657b36cdea88bba Mon Sep 17 00:00:00 2001
+From: Chris Leech <cleech at redhat.com>
+Date: Mon, 24 Dec 2012 13:37:53 -0800
+Subject: iscsid iscsiuio ipc interface
+
+---
+ include/iscsi_err.h    |   2 +
+ usr/Makefile           |   3 +-
+ usr/initiator.c        | 113 ++++++++++++++++++++++++++++++++++++++++++++++++-
+ usr/initiator.h        |   4 ++
+ usr/initiator_common.c |  34 +++++++++++++++
+ usr/iscsi_err.c        |   1 +
+ usr/iscsid_req.c       |  91 +++++++++++++++++++++++++++++++++++++--
+ usr/iscsid_req.h       |   2 +
+ usr/transport.c        |   2 +
+ usr/transport.h        |   3 ++
+ usr/uip_mgmt_ipc.c     |  41 ++++++++++++++++++
+ usr/uip_mgmt_ipc.h     |  73 ++++++++++++++++++++++++++++++++
+ 12 files changed, 364 insertions(+), 5 deletions(-)
+ create mode 100644 usr/uip_mgmt_ipc.c
+ create mode 100644 usr/uip_mgmt_ipc.h
+
+diff --git a/include/iscsi_err.h b/include/iscsi_err.h
+index aabea4e..1139133 100644
+--- a/include/iscsi_err.h
++++ b/include/iscsi_err.h
+@@ -62,6 +62,8 @@ enum {
+ 	ISCSI_ERR_OP_NOT_SUPP		= 27,
+ 	/* device or resource in use */
+ 	ISCSI_ERR_BUSY			= 28,
 +	/* Operation failed, but retrying layer may succeed */
-+	ISCSI_ERR_AGAIN			= 27,
++	ISCSI_ERR_AGAIN			= 29,
  
  	/* Always last. Indicates end of error code space */
  	ISCSI_MAX_ERR_VAL,
-diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/Makefile open-iscsi-2.0-872-rc4-bnx2i.build/libiscsi/Makefile
---- open-iscsi-2.0-872-rc4-bnx2i.base/libiscsi/Makefile	2011-08-14 16:55:23.000000000 -0500
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/libiscsi/Makefile	2011-08-14 16:56:54.000000000 -0500
-@@ -13,7 +13,7 @@ TESTS += tests/test_set_auth tests/test_
- 
- COMMON_SRCS = sysdeps.o
- # sources shared between iscsid, iscsiadm and iscsistart
--ISCSI_LIB_SRCS = netlink.o transport.o cxgbi.o be2iscsi.o iscsi_timer.o initiator_common.o iscsi_err.o session_info.o iscsi_util.o dcb_app.o io.o auth.o discovery.o login.o log.o md5.o sha1.o iface.o idbm.o sysfs.o iscsi_sysfs.o iscsi_net_util.o iscsid_req.o
-+ISCSI_LIB_SRCS = netlink.o uip_mgmt_ipc.o transport.o cxgbi.o be2iscsi.o iscsi_timer.o initiator_common.o iscsi_err.o session_info.o iscsi_util.o dcb_app.o io.o auth.o discovery.o login.o log.o md5.o sha1.o iface.o idbm.o sysfs.o iscsi_sysfs.o iscsi_net_util.o iscsid_req.o
- FW_PARAM_SRCS = fw_entry.o prom_lex.o prom_parse.tab.o fwparam_ppc.o fwparam_sysfs.o
+diff --git a/usr/Makefile b/usr/Makefile
+index 1669890..5bf5f83 100644
+--- a/usr/Makefile
++++ b/usr/Makefile
+@@ -40,7 +40,8 @@ SYSDEPS_SRCS = $(wildcard ../utils/sysdeps/*.o)
+ ISCSI_LIB_SRCS = iscsi_util.o io.o auth.o iscsi_timer.o login.o log.o md5.o \
+ 	sha1.o iface.o idbm.o sysfs.o host.o session_info.o iscsi_sysfs.o \
+ 	iscsi_net_util.o iscsid_req.o transport.o iser.o cxgbi.o be2iscsi.o \
+-	initiator_common.o iscsi_err.o $(IPC_OBJ)  $(SYSDEPS_SRCS)
++	initiator_common.o iscsi_err.o uip_mgmt_ipc.o \
++	$(IPC_OBJ)  $(SYSDEPS_SRCS)
+ # core initiator files
+ INITIATOR_SRCS = initiator.o scsi.o actor.o event_poll.o mgmt_ipc.o kern_err_table.o
  
- # sources shared with the userspace utils, note we build these separately
-diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/initiator.c open-iscsi-2.0-872-rc4-bnx2i.build/usr/initiator.c
---- open-iscsi-2.0-872-rc4-bnx2i.base/usr/initiator.c	2011-08-14 16:49:44.000000000 -0500
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/usr/initiator.c	2011-08-14 16:56:54.000000000 -0500
+diff --git a/usr/initiator.c b/usr/initiator.c
+index d475358..597e0ff 100644
+--- a/usr/initiator.c
++++ b/usr/initiator.c
 @@ -45,6 +45,7 @@
  #include "iscsi_sysfs.h"
  #include "iscsi_settings.h"
@@ -32,8 +58,8 @@ diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/initiator.c open-iscsi-2.0-872
 +#include "host.h"
  #include "sysdeps.h"
  #include "iscsi_err.h"
- 
-@@ -557,6 +558,48 @@ static int iscsi_conn_connect(struct isc
+ #include "kern_err_table.h"
+@@ -557,6 +558,48 @@ static int iscsi_conn_connect(struct iscsi_conn *conn, queue_task_t *qtask)
  	return 0;
  }
  
@@ -82,7 +108,7 @@ diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/initiator.c open-iscsi-2.0-872
  static void
  __session_conn_reopen(iscsi_conn_t *conn, queue_task_t *qtask, int do_stop,
  		      int redirected)
-@@ -598,6 +641,11 @@ __session_conn_reopen(iscsi_conn_t *conn
+@@ -598,6 +641,11 @@ __session_conn_reopen(iscsi_conn_t *conn, queue_task_t *qtask, int do_stop,
  	if (!redirected)
  		session->reopen_cnt++;
  
@@ -94,7 +120,7 @@ diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/initiator.c open-iscsi-2.0-872
  	if (iscsi_conn_connect(conn, qtask)) {
  		delay = ISCSI_CONN_ERR_REOPEN_DELAY;
  		goto queue_reopen;
-@@ -1659,6 +1707,53 @@ failed_login:
+@@ -1670,6 +1718,53 @@ failed_login:
  
  }
  
@@ -148,7 +174,7 @@ diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/initiator.c open-iscsi-2.0-872
  static int iscsi_sched_ev_context(struct iscsi_ev_context *ev_context,
  				  struct iscsi_conn *conn, unsigned long tmo,
  				  int event)
-@@ -1700,6 +1795,11 @@ static int iscsi_sched_ev_context(struct
+@@ -1711,6 +1806,11 @@ static int iscsi_sched_ev_context(struct iscsi_ev_context *ev_context,
  			  ev_context);
  		actor_schedule(&ev_context->actor);
  		break;
@@ -160,7 +186,7 @@ diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/initiator.c open-iscsi-2.0-872
  	case EV_CONN_LOGOUT_TIMER:
  		actor_timer(&ev_context->actor, tmo * 1000,
  			    iscsi_logout_timedout, ev_context);
-@@ -1833,7 +1933,17 @@ session_login_task(node_rec_t *rec, queu
+@@ -1844,7 +1944,17 @@ session_login_task(node_rec_t *rec, queue_task_t *qtask)
  	conn = &session->conn[0];
  	qtask->conn = conn;
  
@@ -179,7 +205,7 @@ diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/initiator.c open-iscsi-2.0-872
  		__session_destroy(session);
  		return ISCSI_ERR_LOGIN;
  	}
-@@ -1990,6 +2100,7 @@ iscsi_host_send_targets(queue_task_t *qt
+@@ -2001,6 +2111,7 @@ iscsi_host_send_targets(queue_task_t *qtask, int host_no, int do_login,
  			struct sockaddr_storage *ss)
  {
  	struct iscsi_transport *t;
@@ -187,10 +213,32 @@ diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/initiator.c open-iscsi-2.0-872
  
  	t = iscsi_sysfs_get_transport_by_hba(host_no);
  	if (!t) {
-diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/initiator_common.c open-iscsi-2.0-872-rc4-bnx2i.build/usr/initiator_common.c
---- open-iscsi-2.0-872-rc4-bnx2i.base/usr/initiator_common.c	2011-08-14 16:49:44.000000000 -0500
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/usr/initiator_common.c	2011-08-14 16:56:54.000000000 -0500
-@@ -561,6 +561,36 @@ TODO handle this
+diff --git a/usr/initiator.h b/usr/initiator.h
+index b45caab..d6dc02e 100644
+--- a/usr/initiator.h
++++ b/usr/initiator.h
+@@ -83,6 +83,7 @@ typedef enum iscsi_event_e {
+ 	EV_CONN_LOGOUT_TIMER,
+ 	EV_CONN_STOP,
+ 	EV_CONN_LOGIN,
++	EV_UIO_POLL,
+ } iscsi_event_e;
+ 
+ struct queue_task;
+@@ -353,5 +354,8 @@ extern void iscsi_copy_operational_params(struct iscsi_conn *conn,
+ extern int iscsi_setup_authentication(struct iscsi_session *session,
+ 				      struct iscsi_auth_config *auth_cfg);
+ extern int iscsi_setup_portal(struct iscsi_conn *conn, char *address, int port);
++extern int iscsi_set_net_config(struct iscsi_transport *t,
++				iscsi_session_t *session,
++				struct iface_rec *iface);
+ 
+ #endif /* INITIATOR_H */
+diff --git a/usr/initiator_common.c b/usr/initiator_common.c
+index ef6820c..eb72795 100644
+--- a/usr/initiator_common.c
++++ b/usr/initiator_common.c
+@@ -562,6 +562,36 @@ TODO handle this
  	return 0;
  }
  
@@ -227,9 +275,9 @@ diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/initiator_common.c open-iscsi-
  int iscsi_host_set_net_params(struct iface_rec *iface,
  			      struct iscsi_session *session)
  {
-@@ -582,6 +612,10 @@ int iscsi_host_set_net_params(struct ifa
- 		return EINVAL;
- 	}
+@@ -600,6 +630,10 @@ int iscsi_host_set_net_params(struct iface_rec *iface,
+ 		log_warning("Could not brining up netdev %s. Try running "
+ 			    "'ifup %s' first if login fails.", netdev, netdev);
  
 +	rc = iscsi_set_net_config(t, session, iface);
 +	if (rc != 0)
@@ -238,29 +286,22 @@ diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/initiator_common.c open-iscsi-
  	rc = host_set_param(t, session->hostno,
  			    ISCSI_HOST_PARAM_IPADDRESS,
  			    iface->ipaddress, ISCSI_STRING);
-diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/initiator.h open-iscsi-2.0-872-rc4-bnx2i.build/usr/initiator.h
---- open-iscsi-2.0-872-rc4-bnx2i.base/usr/initiator.h	2011-08-14 16:49:44.000000000 -0500
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/usr/initiator.h	2011-08-14 16:58:14.000000000 -0500
-@@ -83,6 +83,7 @@ typedef enum iscsi_event_e {
- 	EV_CONN_LOGOUT_TIMER,
- 	EV_CONN_STOP,
- 	EV_CONN_LOGIN,
-+	EV_UIO_POLL,
- } iscsi_event_e;
- 
- struct queue_task;
-@@ -353,5 +354,8 @@ extern void iscsi_copy_operational_param
- extern int iscsi_setup_authentication(struct iscsi_session *session,
- 				      struct iscsi_auth_config *auth_cfg);
- extern int iscsi_setup_portal(struct iscsi_conn *conn, char *address, int port);
-+extern int iscsi_set_net_config(struct iscsi_transport *t,
-+				iscsi_session_t *session,
-+				struct iface_rec *iface);
+diff --git a/usr/iscsi_err.c b/usr/iscsi_err.c
+index 4fe1c53..f9ba130 100644
+--- a/usr/iscsi_err.c
++++ b/usr/iscsi_err.c
+@@ -51,6 +51,7 @@ static char *iscsi_err_msgs[] = {
+ 	/* 26 */ "iSNS registration failed",
+ 	/* 27 */ "operation not supported",
+ 	/* 28 */ "device or resource in use",
++	/* 29 */ "Retryable failure",
+ };
  
- #endif /* INITIATOR_H */
-diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/iscsid_req.c open-iscsi-2.0-872-rc4-bnx2i.build/usr/iscsid_req.c
---- open-iscsi-2.0-872-rc4-bnx2i.base/usr/iscsid_req.c	2011-08-14 16:49:44.000000000 -0500
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/usr/iscsid_req.c	2011-08-14 16:56:54.000000000 -0500
+ char *iscsi_err_to_str(int err)
+diff --git a/usr/iscsid_req.c b/usr/iscsid_req.c
+index 1c4678d..a436194 100644
+--- a/usr/iscsid_req.c
++++ b/usr/iscsid_req.c
 @@ -22,6 +22,7 @@
  #include <stdlib.h>
  #include <string.h>
@@ -284,20 +325,23 @@ diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/iscsid_req.c open-iscsi-2.0-87
 -static int iscsid_connect(int *fd, int start_iscsid)
 +static int ipc_connect(int *fd, char *unix_sock_name, int start_iscsid)
  {
- 	int nsec;
+ 	int nsec, addr_len;
  	struct sockaddr_un addr;
-@@ -67,8 +69,8 @@ static int iscsid_connect(int *fd, int s
+@@ -65,11 +67,11 @@ static int iscsid_connect(int *fd, int start_iscsid)
+ 		return ISCSI_ERR_ISCSID_NOTCONN;
+ 	}
+ 
+-	addr_len = offsetof(struct sockaddr_un, sun_path) + strlen(ISCSIADM_NAMESPACE) + 1;
++	addr_len = offsetof(struct sockaddr_un, sun_path) + strlen(unix_sock_name) + 1;
  
  	memset(&addr, 0, sizeof(addr));
  	addr.sun_family = AF_LOCAL;
--	memcpy((char *) &addr.sun_path + 1, ISCSIADM_NAMESPACE,
--		strlen(ISCSIADM_NAMESPACE));
-+	memcpy((char *) &addr.sun_path + 1, unix_sock_name,
-+		strlen(unix_sock_name));
+-	memcpy((char *) &addr.sun_path + 1, ISCSIADM_NAMESPACE, addr_len);
++	memcpy((char *) &addr.sun_path + 1, unix_sock_name, addr_len);
+ 
  	/*
  	 * Trying to connect with exponential backoff
- 	 */
-@@ -96,6 +98,11 @@ static int iscsid_connect(int *fd, int s
+@@ -98,6 +100,11 @@ static int iscsid_connect(int *fd, int start_iscsid)
  	return ISCSI_ERR_ISCSID_NOTCONN;
  }
  
@@ -309,7 +353,7 @@ diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/iscsid_req.c open-iscsi-2.0-87
  int iscsid_request(int *fd, iscsiadm_req_t *req, int start_iscsid)
  {
  	int err;
-@@ -192,3 +199,81 @@ int iscsid_req_by_sid(iscsiadm_cmd_e cmd
+@@ -194,3 +201,81 @@ int iscsid_req_by_sid(iscsiadm_cmd_e cmd, int sid)
  		return err;
  	return iscsid_req_wait(cmd, fd);
  }
@@ -391,52 +435,30 @@ diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/iscsid_req.c open-iscsi-2.0-87
 +	close(fd);
 +	return err;
 +}
-diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/iscsid_req.h open-iscsi-2.0-872-rc4-bnx2i.build/usr/iscsid_req.h
---- open-iscsi-2.0-872-rc4-bnx2i.base/usr/iscsid_req.h	2011-08-14 16:49:44.000000000 -0500
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/usr/iscsid_req.h	2011-08-14 16:56:54.000000000 -0500
-@@ -33,4 +33,6 @@ extern int iscsid_req_by_rec(int cmd, st
+diff --git a/usr/iscsid_req.h b/usr/iscsid_req.h
+index 68f5256..4fff43d 100644
+--- a/usr/iscsid_req.h
++++ b/usr/iscsid_req.h
+@@ -33,4 +33,6 @@ extern int iscsid_req_by_rec(int cmd, struct node_rec *rec);
  extern int iscsid_req_by_sid_async(int cmd, int sid, int *fd);
  extern int iscsid_req_by_sid(int cmd, int sid);
  
 +extern int uip_broadcast(void *buf, size_t buf_len);
 +
  #endif
-diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/iscsi_err.c open-iscsi-2.0-872-rc4-bnx2i.build/usr/iscsi_err.c
---- open-iscsi-2.0-872-rc4-bnx2i.base/usr/iscsi_err.c	2011-08-14 16:49:44.000000000 -0500
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/usr/iscsi_err.c	2011-08-14 16:56:54.000000000 -0500
-@@ -49,6 +49,7 @@ static char *iscsi_err_msgs[] = {
- 	/* 24 */ "iSCSI login failed due to authorization failure",
- 	/* 25 */ "iSNS query failed",
- 	/* 26 */ "iSNS registration failed",
-+	/* 27 */ "Retryable failure",
- };
- 
- char *iscsi_err_to_str(int err)
-diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/Makefile open-iscsi-2.0-872-rc4-bnx2i.build/usr/Makefile
---- open-iscsi-2.0-872-rc4-bnx2i.base/usr/Makefile	2011-08-14 16:55:23.000000000 -0500
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/usr/Makefile	2011-08-14 16:58:57.000000000 -0500
-@@ -42,7 +42,8 @@ SYSDEPS_SRCS = $(wildcard ../utils/sysde
- ISCSI_LIB_SRCS = iscsi_util.o io.o auth.o iscsi_timer.o login.o log.o md5.o \
- 	sha1.o iface.o idbm.o sysfs.o host.o session_info.o iscsi_sysfs.o \
- 	iscsi_net_util.o iscsid_req.o transport.o cxgbi.o be2iscsi.o \
--	initiator_common.o iscsi_err.o $(IPC_OBJ)  $(SYSDEPS_SRCS) $(DCB_OBJ)
-+	initiator_common.o iscsi_err.o uip_mgmt_ipc.o \
-+	$(IPC_OBJ)  $(SYSDEPS_SRCS) $(DCB_OBJ)
- # core initiator files
- INITIATOR_SRCS = initiator.o scsi.o actor.o event_poll.o mgmt_ipc.o
- 
-diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/transport.c open-iscsi-2.0-872-rc4-bnx2i.build/usr/transport.c
---- open-iscsi-2.0-872-rc4-bnx2i.base/usr/transport.c	2011-08-14 16:49:44.000000000 -0500
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/usr/transport.c	2011-08-14 16:56:54.000000000 -0500
-@@ -25,6 +25,7 @@
+diff --git a/usr/transport.c b/usr/transport.c
+index e6e3dfc..10212af 100644
+--- a/usr/transport.c
++++ b/usr/transport.c
+@@ -35,6 +35,7 @@
  #include "log.h"
  #include "iscsi_util.h"
  #include "iscsi_sysfs.h"
 +#include "uip_mgmt_ipc.h"
  #include "cxgbi.h"
  #include "be2iscsi.h"
- 
-@@ -67,6 +68,7 @@ struct iscsi_transport_template bnx2i = 
+ #include "iser.h"
+@@ -79,6 +80,7 @@ struct iscsi_transport_template bnx2i = {
  	.ep_connect	= ktransport_ep_connect,
  	.ep_poll	= ktransport_ep_poll,
  	.ep_disconnect	= ktransport_ep_disconnect,
@@ -444,9 +466,10 @@ diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/transport.c open-iscsi-2.0-872
  };
  
  struct iscsi_transport_template be2iscsi = {
-diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/transport.h open-iscsi-2.0-872-rc4-bnx2i.build/usr/transport.h
---- open-iscsi-2.0-872-rc4-bnx2i.base/usr/transport.h	2011-08-14 16:49:34.000000000 -0500
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/usr/transport.h	2011-08-14 16:56:54.000000000 -0500
+diff --git a/usr/transport.h b/usr/transport.h
+index 672561b..5dcf872 100644
+--- a/usr/transport.h
++++ b/usr/transport.h
 @@ -35,6 +35,9 @@ struct iscsi_transport_template {
  	int (*ep_poll) (struct iscsi_conn *conn, int timeout_ms);
  	void (*ep_disconnect) (struct iscsi_conn *conn);
@@ -457,9 +480,11 @@ diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/transport.h open-iscsi-2.0-872
  };
  
  /* represents data path provider */
-diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/uip_mgmt_ipc.c open-iscsi-2.0-872-rc4-bnx2i.build/usr/uip_mgmt_ipc.c
---- open-iscsi-2.0-872-rc4-bnx2i.base/usr/uip_mgmt_ipc.c	1969-12-31 18:00:00.000000000 -0600
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/usr/uip_mgmt_ipc.c	2011-08-14 16:56:54.000000000 -0500
+diff --git a/usr/uip_mgmt_ipc.c b/usr/uip_mgmt_ipc.c
+new file mode 100644
+index 0000000..73b1632
+--- /dev/null
++++ b/usr/uip_mgmt_ipc.c
 @@ -0,0 +1,41 @@
 +/*
 + * uIP iSCSI Daemon/Admin Management IPC
@@ -502,9 +527,11 @@ diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/uip_mgmt_ipc.c open-iscsi-2.0-
 +			     sizeof(iscsid_uip_broadcast_header_t) +
 +			     sizeof(*iface));
 +}
-diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/uip_mgmt_ipc.h open-iscsi-2.0-872-rc4-bnx2i.build/usr/uip_mgmt_ipc.h
---- open-iscsi-2.0-872-rc4-bnx2i.base/usr/uip_mgmt_ipc.h	1969-12-31 18:00:00.000000000 -0600
-+++ open-iscsi-2.0-872-rc4-bnx2i.build/usr/uip_mgmt_ipc.h	2011-08-14 16:56:54.000000000 -0500
+diff --git a/usr/uip_mgmt_ipc.h b/usr/uip_mgmt_ipc.h
+new file mode 100644
+index 0000000..3859688
+--- /dev/null
++++ b/usr/uip_mgmt_ipc.h
 @@ -0,0 +1,73 @@
 +/*
 + * uIP iSCSI Daemon/Admin Management IPC
@@ -579,3 +606,6 @@ diff -Naurp open-iscsi-2.0-872-rc4-bnx2i.base/usr/uip_mgmt_ipc.h open-iscsi-2.0-
 +
 +
 +#endif /* UIP_MGMT_IPC_H */
+-- 
+1.7.11.7
+
diff --git a/0071-iscsiuio-0.7.4.3.patch b/0071-iscsiuio-0.7.4.3.patch
new file mode 100644
index 0000000..9530a5e
--- /dev/null
+++ b/0071-iscsiuio-0.7.4.3.patch
@@ -0,0 +1,5730 @@
+From bd534355001eab5bcb4f2473dd71594b44c97d63 Mon Sep 17 00:00:00 2001
+From: Chris Leech <cleech at redhat.com>
+Date: Wed, 19 Dec 2012 21:27:45 -0800
+Subject: iscsiuio 0.7.4.3
+
+---
+ README                  |  15 +-
+ RELEASE.TXT             | 228 +++++++++++-
+ configure               |  18 +-
+ configure.ac            |   6 +-
+ docs/iscsiuio.8         |   4 +-
+ include/iscsi_if.h      |   3 +
+ src/apps/dhcpc/dhcpc.c  |   6 +-
+ src/apps/dhcpc/dhcpv6.c |   8 +-
+ src/apps/dhcpc/dhcpv6.h |   2 +-
+ src/uip/ipv6.c          | 222 ++++++------
+ src/uip/ipv6.h          |   3 +-
+ src/uip/ipv6_ndpc.c     |  87 +++--
+ src/uip/uip.c           |   4 +-
+ src/uip/uip.h           |  21 +-
+ src/uip/uip_arp.c       |   8 +-
+ src/unix/iscsid_ipc.c   | 600 ++++++++++++++++++++-----------
+ src/unix/libs/bnx2.c    |  85 +++--
+ src/unix/libs/bnx2x.c   | 134 ++++---
+ src/unix/libs/bnx2x.h   |  12 +
+ src/unix/libs/cnic.c    | 252 ++++---------
+ src/unix/libs/cnic.h    |   3 +-
+ src/unix/main.c         |   1 -
+ src/unix/nic.c          | 931 +++++++++++++++++++++---------------------------
+ src/unix/nic.h          |  50 ++-
+ src/unix/nic_nl.c       | 404 ++++++++++++---------
+ src/unix/nic_utils.c    | 267 +++++++-------
+ src/unix/nic_utils.h    |   4 +-
+ src/unix/nic_vlan.c     |   3 +-
+ src/unix/packet.c       |   4 +-
+ 29 files changed, 1856 insertions(+), 1529 deletions(-)
+
+diff --git a/README b/README
+index 5c36dec..a716263 100644
+--- a/README
++++ b/README
+@@ -1,6 +1,6 @@
+-Iscsiuio Userspace Tool
+-Version 0.7.2.1
+-Mar 05, 2012
++iscsiuio Userspace Tool
++Version 0.7.4.3
++Aug 16, 2012
+ ------------------------------------------------------
+ 
+ This tool is to be used in conjunction with the Broadcom NetXtreme II Linux
+@@ -189,10 +189,11 @@ To run the daemon in debug mode please pass the parameter  '-d <debug level>'
+ 
+ where the following debug levels are defined:
+ 
+-DEBUG         4 - Print all messages
+-INFO          3 - Print messages needed to follow the uIP code (default)
+-WARN          2 - Print warning messages
+-ERROR         1 - Only print critical errors
++PACKET		5 - Print all messages
++DEBUG		4 - Print debug messages
++INFO		3 - Print messages needed to follow the uIP code (default)
++WARN		2 - Print warning messages
++ERROR		1 - Only print critical errors
+ 
+ A sample banner message:
+ 
+diff --git a/RELEASE.TXT b/RELEASE.TXT
+index d4a00b6..cb1d470 100644
+--- a/RELEASE.TXT
++++ b/RELEASE.TXT
+@@ -1,7 +1,7 @@
+                               Release Notes
+                         Broadcom uIP Linux Driver
+-                            Version 0.7.2.1
+-                               03/05/2012
++                            Version 0.7.4.3
++                               08/16/2012
+ 
+                           Broadcom Corporation
+                          5300 California Avenue,
+@@ -10,6 +10,228 @@
+                Copyright (c) 2004 - 2012 Broadcom Corporation
+                            All rights reserved
+ 
++
++uIP v0.7.4.3 (Aug 16, 2012)
++=======================================================
++   Fixes
++   -----
++   1. Problem: Cont00049383 - No mechanism in iface file to support
++               gateway/routing
++      Change:  Added support for the additional network parameters
++               as passed from the newer iscsi-util.
++               These parameters include:
++               IPv4: subnet_mask, gateway
++               IPv6: ipv6_linklocal, ipv6_router,
++                     ipv6_autocfg, linklocal_autocfg, router_autocfg
++               VLAN: vlan_id, vlan_priority, vlan_state
++               Other: mtu, port
++      Impact:  All
++
++   2. Problem: Cont00060806 - Unable to connect target using DHCP over
++               tagged VLAN
++      Change:  DHCP+VLAN is a new feature enhancement that was added
++               alongside all other new iface parameters.
++      Impact:  All
++
++   3. Problem: Cont00061513 - Unable to connect to target over VLAN
++               interface
++      Cause:   The VLAN id was not properly passed back to the CNIC
++               driver for the offload request
++      Change:  Fixed the VLAN id being passed back to the CNIC driver
++      Impact:  All
++
++   4. Problem: Cont00061529 - Unable to connect to target after an
++               initial failed login attempt until iscsi service is
++               restarted
++      Cause:   Upon a failed DHCPv4 acquisition due to the wrong VLAN
++               tag in the initial iface setup, any iscsid connect request
++               from the same NIC will get dropped due to a bug.
++      Change:  Fixed the bug which prevented new iscsid connect requests
++               from getting honored
++      Impact:  All
++
++   5. Problem: Cont00061978 - Load/unload stress test fails
++      Cause:   The bnx2x open request was failing due to the module
++               request procedure.  However, the open failure was
++               not being handled correctly.
++      Change:  Fixed the device open error handling
++      Impact:  5771X/578XX
++
++   6. Problem: Cont00062170 - IPv6 login/logout stress fails
++      Cause:   The packet buffer routine for IPv6 did not take
++               network order <-> host order into consideration
++      Change:  Added a htons call to compensate for the ntohs pair
++      Impact:  All
++
++   7. Problem: Cont00061869 - Unable to setup an offload iSCSI
++               connection with FLR/NPAR under ESX5.0:PDA
++      Cause:   The physical function ID was previously extracted
++               from the sysfs of the VM which might not be consistent
++               to the actual physical setup due to the function
++               remapping in the hypervisor
++      Change:  Read the physical function ID directly from the BAR0
++               ME register
++      Impact:  All
++
++   8. Problem: Cont00062170 - IPv6 login/logout stress fails
++      Cause:   The packet interrupt was lost after running the test
++               for a much longer period of time.  A bug in the
++               packet processing routine was found to exit prematurely
++      Change:  Fixed the packet processing routine to process all
++               packets before exiting
++      Impact:  All
++
++   9. Problem: Cont00062660 - Unable to login with VLAN iscsiuio
++               on RHEL6.2
++      Cause:   The open-iscsi util in RHEL6.2 has a bug which
++               does not pass the correct iface_num to iscsiuio
++      Change:  Added workaround to fall back to do the legacy
++               VLAN support if iface_num and vlan_id = 0
++      Impact:  RHEL6.2
++
++  10. Problem: Cont00062805 - Cannot login to iSCSI targets on RHEL6.3
++      Cause:   The problem was caused by a change made to the iface_rec
++               structure in the RHEL6.3 inbox open-iscsi util
++      Change:  The new changes is now incorporated
++      Impact:  All
++
++  11. Problem: Cont00062993 - IPv6 DHCP with VLAN specification in
++               iface file gets wrong address
++      Cause:   The DHCPv6 request was using the same DUID as always
++               so the non-VLAN DHCP server responded to our broadcast
++               instead
++      Change:  Changed the DHCPv6 request DUID to link address + time
++               instead of link address alone
++      Impact:  DHCPv6 operation
++
++  12. Problem: RHEL BZ 734010/804580 - issues found by the Coverity
++               scan
++      Cause:   10 code issues were flagged for revision
++      Change:  Fixed all area of concern
++      Impact:  All
++
++  13. Problem: Cont00063177 - IPv4 DHCP with VLAN specification in
++               iface file gets wrong address
++      Cause:   The DHCPv4 handler was not discriminating the VLAN tag
++               associated with the DHCP offers from multiple DHCP
++               servers
++      Change:  Changed the DHCPv4 handler to drop DHCP offer packets
++               that doesn't match the VLAN tag of the intended DHCP
++               discovery packet
++      Impact:  DHCPv4 operation
++
++  14. Problem: Cont00063421 - Static IPv6 cannot connect via RA/LL
++      Cause:   The router advertise and the linklocal address
++               were corrupted due to the override capabilities
++               added for the newer open-iscsi util
++      Change:  Fixed the address override code
++      Impact:  Static IPv6
++
++  15. Problem: Cont00063443 - Compilation error on SLES11sp1
++      Cause:   The iface_num field was not defined
++      Change:  Fixed all references to iface_num
++      Impact:  SLES11sp1
++
++  16. Problem: Cont00063518 - HBA fails to connect across router
++               using iface.gateway address
++      Cause:   The gateway override code did not populate the
++               address into the lower level engine
++      Change:  Fixed the gateway override code
++      Impact:  IPv4 Static IP operation
++
++  17. Problem: Cont00063567 - IPv6 LL and RA override does not work
++      Cause:   The IPv6 LL/RA override addresses were overwritten
++               by the NDP engine
++      Change:  Fixed the LL/RA override code
++      Impact:  IPv6 operation
++
++  18. Problem: Cont00063626 - Static IPv6 does not connect when
++               the prefix len is not set explicitly
++      Cause:   The IPv6 prefix length was not set correctly
++               for Static IPv6 operation when CIDR notation is
++               not specified
++      Change:  Fixed the default prefix length
++      Impact:  Static IPv6
++
++  19. Problem: Cont00063651 - Cannot connect to iSCSI targets
++               HP PTM/SF
++      Cause:   Switch-Dependent mode + invalid Outer VLAN was
++               not supported
++      Change:  Allow SD+invalid OV to fallback to SF operation mode
++      Impact:  5771X/578XX
++
++  20. Problem: Cont00063816 - The initiator is not able to connect
++               to the iSCSI targets over VLAN
++      Cause:   The process packet routine did not consider the PCP
++               of the VLAN tag to be non-zero.  This created a
++               mismatch when this VLAN tag was compared against the
++               nic_iface->vlan_id which doesn't include the PCP.
++      Change:  Added the consideration of non-zero PCP
++      Impact:  All
++
++  21. Problem: Cont00063863 - can't boot into offload image
++               when VLAN is enabled
++      Cause:   During the iSCSI login exchange, certain iSCSI targets
++               will send an ARP request even though the TCP connection
++               has been made.  The bug was in this ARP reply where
++               the local MAC was corrupted when VLAN is enabled.
++      Change:  Fixed the ARP reply packet
++      Impact:  All
++
++  22. Problem: Cont00063863 - can't boot into offload image
++               when VLAN is enabled
++      Cause:   During the iSCSI login exchange, certain iSCSI targets
++               will send an ARP request even though the TCP connection
++               has been made.  The bug was in this ARP reply where
++               the local MAC was corrupted when VLAN is enabled.
++      Change:  Fixed the ARP reply packet
++      Impact:  All
++
++  23. Problem: Cont00064604 - Fails to connect to routed IPv6 target
++               via RA
++      Cause:   The default router IPv6 address was not being retrieved
++               correctly.
++      Change:  Fixed the default router IPv6 address read
++      Impact:  All
++
++  24. Problem: Cont00064665 - Linux iSCSI connects via gateway address
++               on the wrong subnet
++      Cause:   The gateway address used was not checked against the
++               subnet mask specified before the ARP requests.  Since
++               this behavior deters from how L2 operates, therefore,
++               a change was made to correct this.
++      Change:  Added check of the gateway specified against the subnet
++               specified.
++      Impact:  Static IPv4 operation
++
++  25. Problem: Cont00064722 - Linux iSCSI unable to force IPv6 LL
++               override (advanced iface parameters)
++      Cause:   The override LL address was not being populated to the
++               IPv6 address database correctly
++      Change:  Added this correctly to the IPv6 initialization
++      Impact:  Static/DHCP IPv6 LL address override only
++
++   Enhancements
++   ------------
++   1. Lock iscsid's connect request with path_req so connect requests
++      with DHCP/Static will no longer override each other
++
++   2. Fixed the if_down handler from global to nic specific
++
++   3. Fixed various synchronization issues
++
++   4. Updated README
++
++   5. Added support for the new iface_num field in the iscsi_uevent
++      path
++
++   6. Fixed bug in the nic_iface search engine based on iface_num
++
++   7. Allow VLAN tag = 1 (router management) to connect offload
++
++   8. Added support for jumbo MTU (independent from the L2 MTU)
++
++
+ uIP v0.7.2.1 (Mar 05, 2012)
+ =======================================================
+    Fixes
+@@ -47,7 +269,7 @@ uIP v0.7.2.1 (Mar 05, 2012)
+    ------------
+    1. Change:  Default iscsiuio logging to off.  Use the '-d'
+                option to enable
+-   2. Change:  Disable HP SD mode
++   2. Change:  Disable HP SD mode (NOT)
+    3. Change:  Updated README
+ 
+ 
+diff --git a/configure b/configure
+index 4879fb9..6ff2e68 100755
+--- a/configure
++++ b/configure
+@@ -1,6 +1,6 @@
+ #! /bin/sh
+ # Guess values for system-dependent variables and create Makefiles.
+-# Generated by GNU Autoconf 2.59 for iscsiuio 0.7.2.1.
++# Generated by GNU Autoconf 2.59 for iscsiuio 0.7.4.3.
+ #
+ # Report bugs to <eddie.wai at broadcom.com>.
+ #
+@@ -423,8 +423,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
+ # Identity of this package.
+ PACKAGE_NAME='iscsiuio'
+ PACKAGE_TARNAME='iscsiuio'
+-PACKAGE_VERSION='0.7.2.1'
+-PACKAGE_STRING='iscsiuio 0.7.2.1'
++PACKAGE_VERSION='0.7.4.3'
++PACKAGE_STRING='iscsiuio 0.7.4.3'
+ PACKAGE_BUGREPORT='eddie.wai at broadcom.com'
+ 
+ # Factoring default headers for most tests.
+@@ -954,7 +954,7 @@ if test "$ac_init_help" = "long"; then
+   # Omit some internal or obsolete options to make the list less imposing.
+   # This message is too long to be a string in the A/UX 3.1 sh.
+   cat <<_ACEOF
+-\`configure' configures iscsiuio 0.7.2.1 to adapt to many kinds of systems.
++\`configure' configures iscsiuio 0.7.4.3 to adapt to many kinds of systems.
+ 
+ Usage: $0 [OPTION]... [VAR=VALUE]...
+ 
+@@ -1020,7 +1020,7 @@ fi
+ 
+ if test -n "$ac_init_help"; then
+   case $ac_init_help in
+-     short | recursive ) echo "Configuration of iscsiuio 0.7.2.1:";;
++     short | recursive ) echo "Configuration of iscsiuio 0.7.4.3:";;
+    esac
+   cat <<\_ACEOF
+ 
+@@ -1161,7 +1161,7 @@ fi
+ test -n "$ac_init_help" && exit 0
+ if $ac_init_version; then
+   cat <<\_ACEOF
+-iscsiuio configure 0.7.2.1
++iscsiuio configure 0.7.4.3
+ generated by GNU Autoconf 2.59
+ 
+ Copyright (C) 2003 Free Software Foundation, Inc.
+@@ -1175,7 +1175,7 @@ cat >&5 <<_ACEOF
+ This file contains any messages produced by compilers while
+ running configure, to aid debugging if configure makes a mistake.
+ 
+-It was created by iscsiuio $as_me 0.7.2.1, which was
++It was created by iscsiuio $as_me 0.7.4.3, which was
+ generated by GNU Autoconf 2.59.  Invocation command line was
+ 
+   $ $0 $@
+@@ -21726,7 +21726,7 @@ _ASBOX
+ } >&5
+ cat >&5 <<_CSEOF
+ 
+-This file was extended by iscsiuio $as_me 0.7.2.1, which was
++This file was extended by iscsiuio $as_me 0.7.4.3, which was
+ generated by GNU Autoconf 2.59.  Invocation command line was
+ 
+   CONFIG_FILES    = $CONFIG_FILES
+@@ -21789,7 +21789,7 @@ _ACEOF
+ 
+ cat >>$CONFIG_STATUS <<_ACEOF
+ ac_cs_version="\\
+-iscsiuio config.status 0.7.2.1
++iscsiuio config.status 0.7.4.3
+ configured by $0, generated by GNU Autoconf 2.59,
+   with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
+ 
+diff --git a/configure.ac b/configure.ac
+index 3b7a880..0b1e7f1 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1,6 +1,6 @@
+ dnl iscsiuio uIP user space stack configure.ac file
+ dnl
+-dnl Copyright (c) 2004-2011 Broadcom Corporation
++dnl Copyright (c) 2004-2012 Broadcom Corporation
+ dnl
+ dnl This program is free software; you can redistribute it and/or modify
+ dnl it under the terms of the GNU General Public License as published by
+@@ -11,9 +11,9 @@ dnl Maintained by: Eddie Wai (eddie.wai at broadcom.com)
+ dnl
+ 
+ PACKAGE=iscsiuio
+-VERSION=0.7.2.1
++VERSION=0.7.4.3
+ 
+-AC_INIT(iscsiuio, 0.7.2.1, eddie.wai at broadcom.com)
++AC_INIT(iscsiuio, 0.7.4.3, eddie.wai at broadcom.com)
+ 
+ AM_INIT_AUTOMAKE($PACKAGE, $VERSION)
+ AC_CONFIG_HEADER(config.h)
+diff --git a/docs/iscsiuio.8 b/docs/iscsiuio.8
+index 3307b1e..4bf26df 100644
+--- a/docs/iscsiuio.8
++++ b/docs/iscsiuio.8
+@@ -3,9 +3,9 @@
+ .\" modify it under the terms of the GNU General Public License as
+ .\" published by the Free Software Foundation.
+ .\"
+-.\" bnx2.4,v 0.7.2.1
++.\" bnx2.4,v 0.7.4.3
+ .\"
+-.TH iscsiuio 8 "03/05/2012" "Broadcom Corporation"
++.TH iscsiuio 8 "08/16/2012" "Broadcom Corporation"
+ .\"
+ .\" NAME part
+ .\"
+diff --git a/include/iscsi_if.h b/include/iscsi_if.h
+index a9ac145..1944abd 100644
+--- a/include/iscsi_if.h
++++ b/include/iscsi_if.h
+@@ -207,6 +207,7 @@ struct iscsi_uevent {
+ 		} ep_connect_ret;
+                 struct msg_req_path {
+ 			uint32_t        host_no;
++			uint32_t	iface_num;
+ 		} req_path;
+ 		struct msg_notify_if_down {
+ 			uint32_t        host_no;
+@@ -234,6 +235,8 @@ struct iscsi_path {
+ 		struct in6_addr v6_addr;
+ 	} dst;
+ 	uint16_t        vlan_id;
++#define IFACE_NUM_PRESENT (1<<0)
++#define IFACE_NUM_INVALID -1
+ 	uint16_t        pmtu;
+ }  __attribute__ ((aligned (sizeof(uint64_t))));
+ 
+diff --git a/src/apps/dhcpc/dhcpc.c b/src/apps/dhcpc/dhcpc.c
+index 88d75c3..afec601 100644
+--- a/src/apps/dhcpc/dhcpc.c
++++ b/src/apps/dhcpc/dhcpc.c
+@@ -334,7 +334,7 @@ static PT_THREAD(handle_dhcp(struct uip_stack *ustack))
+ 		      (uint8_t *) s->mac_addr);
+ 
+ 	/*  Put the stack thread back into a long sleep */
+-	s->nic->state |= NIC_LONG_SLEEP;
++	s->nic->flags |= NIC_LONG_SLEEP;
+ 
+ 	/*  timer_stop(&s.timer); */
+ 
+@@ -343,7 +343,7 @@ static PT_THREAD(handle_dhcp(struct uip_stack *ustack))
+ 	timer_set(&s->timer, s->ticks);
+ 	PT_WAIT_UNTIL(&s->pt, timer_expired(&s->timer));
+ 	LOG_INFO("Lease expired, re-acquire IP address");
+-	s->nic->state &= ~NIC_LONG_SLEEP;
++	s->nic->flags &= ~NIC_LONG_SLEEP;
+ 	PT_RESTART(&s->pt);
+ 
+ 	/*
+@@ -397,7 +397,7 @@ int dhcpc_init(nic_t * nic, struct uip_stack *ustack,
+ 	ustack->dhcpc = s;
+ 
+ 	/* Let the RX poll value take over */
+-	nic->state &= ~NIC_LONG_SLEEP;
++	nic->flags &= ~NIC_LONG_SLEEP;
+ 
+ 	PT_INIT(&s->pt);
+ 
+diff --git a/src/apps/dhcpc/dhcpv6.c b/src/apps/dhcpc/dhcpv6.c
+index b7ae631..273cce0 100644
+--- a/src/apps/dhcpc/dhcpv6.c
++++ b/src/apps/dhcpc/dhcpv6.c
+@@ -86,10 +86,6 @@ int dhcpv6_do_discovery(pDHCPV6_CONTEXT dhcpv6_context)
+ 	    (pIPV6_HDR) dhcpv6_context->ipv6_context->ustack->network_layer;
+ 	dhcpv6_context->udp =
+ 	    (pUDP_HDR) ((u8_t *) dhcpv6_context->ipv6 + sizeof(IPV6_HDR));
+-	LOG_INFO("dhcpv6: ipv6c=%p, ustack=%p eth=%p ipv6=%p udp=%p",
+-		 dhcpv6_context->ipv6_context,
+-		 dhcpv6_context->ipv6_context->ustack, dhcpv6_context->eth,
+-		 dhcpv6_context->ipv6, dhcpv6_context->udp);
+ 
+ 	/* Send out DHCPv6 Solicit packet. */
+ 	dhcpv6_send_solicit_packet(dhcpv6_context);
+@@ -176,8 +172,10 @@ STATIC u16_t dhcpv6_init_packet(pDHCPV6_CONTEXT dhcpv6_context, u8_t type)
+ 	opt->hdr.type = HOST_TO_NET16(DHCPV6_OPT_CLIENTID);
+ 	opt->hdr.length = HOST_TO_NET16(sizeof(DHCPV6_OPT_CLIENT_ID));
+ 	opt->type.client_id.duid_type =
+-	    HOST_TO_NET16(DHCPV6_DUID_TYPE_LINK_LAYER);
++	    HOST_TO_NET16(DHCPV6_DUID_TYPE_LINK_LAYER_AND_TIME);
+ 	opt->type.client_id.hw_type = HOST_TO_NET16(DHCPV6_HW_TYPE_ETHERNET);
++	opt->type.client_id.time = HOST_TO_NET32(clock_time()/1000 -
++						 0x3A4FC880);
+ 	memcpy((char __FAR__ *)&opt->type.client_id.link_layer_addr,
+ 	       (char __FAR__ *)dhcpv6_context->our_mac_addr, sizeof(MAC_ADDR));
+ 	pkt_len += sizeof(DHCPV6_OPT_CLIENT_ID) + sizeof(DHCPV6_OPT_HDR);
+diff --git a/src/apps/dhcpc/dhcpv6.h b/src/apps/dhcpc/dhcpv6.h
+index 917cf35..d8e03e5 100644
+--- a/src/apps/dhcpc/dhcpv6.h
++++ b/src/apps/dhcpc/dhcpv6.h
+@@ -164,7 +164,7 @@ typedef struct DHCPV6_OPT_CLIENT_ID {
+ #define DHCPV6_DUID_TYPE_LINK_LAYER          3
+ 	u16_t hw_type;
+ #define DHCPV6_HW_TYPE_ETHERNET              1
+-//  u32_t time;
++	u32_t time;
+ 	MAC_ADDR link_layer_addr;
+ } DHCPV6_OPT_CLIENT_ID, *pDHCPV6_OPT_CLIENT_ID;
+ 
+diff --git a/src/uip/ipv6.c b/src/uip/ipv6.c
+index 594495a..a8eed71 100644
+--- a/src/uip/ipv6.c
++++ b/src/uip/ipv6.c
+@@ -38,6 +38,7 @@
+  */
+ #include <stdio.h>
+ #include <string.h>
++#include <arpa/inet.h>
+ #include "logger.h"
+ #include "uip.h"
+ #include "ipv6.h"
+@@ -78,7 +79,7 @@ STATIC void ipv6_udp_rx(pIPV6_CONTEXT ipv6_context);
+ 
+ int iscsiL2Send(pIPV6_CONTEXT ipv6_context, int pkt_len)
+ {
+-	LOG_DEBUG("IPV6: iscsiL2Send");
++	LOG_DEBUG("IPv6: iscsiL2Send");
+ 	uip_send(ipv6_context->ustack,
+ 		 (void *)ipv6_context->ustack->data_link_layer, pkt_len);
+ 
+@@ -103,7 +104,8 @@ int iscsiL2AddMcAddr(pIPV6_CONTEXT ipv6_context, MAC_ADDR * new_mc_addr)
+ 			    (char __FAR__ *)&all_zeroes_mc, sizeof(MAC_ADDR))) {
+ 			memcpy((char __FAR__ *)mc_addr,
+ 			       (char __FAR__ *)new_mc_addr, sizeof(MAC_ADDR));
+-			LOG_DEBUG("IPV6: mc_addr added %x:%x:%x:%x:%x:%x",
++			LOG_DEBUG("IPv6: mc_addr added "
++				  "%02x:%02x:%02x:%02x:%02x:%02x",
+ 				  *(u8_t *) new_mc_addr,
+ 				  *((u8_t *) new_mc_addr + 1),
+ 				  *((u8_t *) new_mc_addr + 2),
+@@ -150,10 +152,11 @@ void ipv6_init(struct ndpc_state *ndp, int cfg)
+ 	ipv6_arp_table = &ipv6_context->ipv6_arp_table[0];
+ 	ipv6_prefix_table = &ipv6_context->ipv6_prefix_table[0];
+ 
+-	memset((char __FAR__ *)ipv6_arp_table, 0, sizeof(ipv6_arp_table));
+-	memset((char __FAR__ *)ipv6_prefix_table, 0, sizeof(ipv6_prefix_table));
+-	memcpy((char __FAR__ *)&ipv6_context->mac_addr,
+-	       (char __FAR__ *)mac_addr, sizeof(MAC_ADDR));
++	memset((char __FAR__*)ipv6_arp_table, 0, sizeof(*ipv6_arp_table));
++	memset((char __FAR__*)ipv6_prefix_table, 0,
++	       sizeof(*ipv6_prefix_table));
++	memcpy((char __FAR__*)&ipv6_context->mac_addr,
++	       (char __FAR__*)mac_addr, sizeof(MAC_ADDR));
+ 	/* 
+ 	 * Per RFC 2373.  
+ 	 * There are two types of local-use unicast addresses defined.  These
+@@ -167,33 +170,34 @@ void ipv6_init(struct ndpc_state *ndp, int cfg)
+ 	 * |1111111010|           0             |       interface ID         |
+ 	 * +----------+-------------------------+----------------------------+
+ 	 */
+-	ipv6_context->link_local_addr.addr8[0] = 0xfe;
+-	ipv6_context->link_local_addr.addr8[1] = 0x80;
+-	/* Bit 1 is 1 to indicate universal scope. */
+-	ipv6_context->link_local_addr.addr8[8] = mac_addr[0] | 0x2;
+-	ipv6_context->link_local_addr.addr8[9] = mac_addr[1];
+-	ipv6_context->link_local_addr.addr8[10] = mac_addr[2];
+-	ipv6_context->link_local_addr.addr8[11] = 0xff;
+-	ipv6_context->link_local_addr.addr8[12] = 0xfe;
+-	ipv6_context->link_local_addr.addr8[13] = mac_addr[3];
+-	ipv6_context->link_local_addr.addr8[14] = mac_addr[4];
+-	ipv6_context->link_local_addr.addr8[15] = mac_addr[5];
+-
+-	ipv6_context->link_local_multi.addr8[0] = 0xff;
+-	ipv6_context->link_local_multi.addr8[1] = 0x02;
+-	ipv6_context->link_local_multi.addr8[11] = 0x01;
+-	ipv6_context->link_local_multi.addr8[12] = 0xff;
+-	ipv6_context->link_local_multi.addr8[13] |=
+-	    ipv6_context->link_local_addr.addr8[13];
+-	ipv6_context->link_local_multi.addr16[7] =
+-	    ipv6_context->link_local_addr.addr16[7];
+-
+-	/* Default Prefix length is 64 */
+-	/* Add Link local address to the head of the ipv6 address
+-	   list */
+-	ipv6_add_prefix_entry(ipv6_context,
+-			      &ipv6_context->link_local_addr, 64);
+-
++	if (ipv6_context->ustack->linklocal_autocfg != IPV6_LL_AUTOCFG_OFF) {
++		ipv6_context->link_local_addr.addr8[0] = 0xfe;
++		ipv6_context->link_local_addr.addr8[1] = 0x80;
++		/* Bit 1 is 1 to indicate universal scope. */
++		ipv6_context->link_local_addr.addr8[8] = mac_addr[0] | 0x2;
++		ipv6_context->link_local_addr.addr8[9] = mac_addr[1];
++		ipv6_context->link_local_addr.addr8[10] = mac_addr[2];
++		ipv6_context->link_local_addr.addr8[11] = 0xff;
++		ipv6_context->link_local_addr.addr8[12] = 0xfe;
++		ipv6_context->link_local_addr.addr8[13] = mac_addr[3];
++		ipv6_context->link_local_addr.addr8[14] = mac_addr[4];
++		ipv6_context->link_local_addr.addr8[15] = mac_addr[5];
++
++		ipv6_context->link_local_multi.addr8[0] = 0xff;
++		ipv6_context->link_local_multi.addr8[1] = 0x02;
++		ipv6_context->link_local_multi.addr8[11] = 0x01;
++		ipv6_context->link_local_multi.addr8[12] = 0xff;
++		ipv6_context->link_local_multi.addr8[13] |=
++		    ipv6_context->link_local_addr.addr8[13];
++		ipv6_context->link_local_multi.addr16[7] =
++		    ipv6_context->link_local_addr.addr16[7];
++
++		/* Default Prefix length is 64 */
++		/* Add Link local address to the head of the ipv6 address
++		   list */
++		ipv6_add_prefix_entry(ipv6_context,
++				      &ipv6_context->link_local_addr, 64);
++	}
+ 	/*
+ 	 * Convert Multicast IP address to Multicast MAC adress per 
+ 	 * RFC 2464: Transmission of IPv6 Packets over Ethernet Networks
+@@ -257,6 +261,7 @@ int ipv6_add_prefix_entry(pIPV6_CONTEXT ipv6_context,
+ 	int i;
+ 	pIPV6_PREFIX_ENTRY prefix_entry;
+ 	pIPV6_PREFIX_ENTRY ipv6_prefix_table = ipv6_context->ipv6_prefix_table;
++	char addr_str[INET6_ADDRSTRLEN];
+ 
+ 	/* Check if there is an valid entry already. */
+ 	for (i = 0; i < IPV6_NUM_OF_ADDRESS_ENTRY; i++) {
+@@ -287,21 +292,13 @@ int ipv6_add_prefix_entry(pIPV6_CONTEXT ipv6_context,
+ 
+ 	prefix_entry->prefix_len = prefix_len / 8;
+ 
+-	memcpy((char __FAR__ *)&prefix_entry->address,
+-	       (char __FAR__ *)ipv6_addr, sizeof(IPV6_ADDR));
+-
+-
+-	LOG_DEBUG("IPV6: add prefix ip addr "
+-		  "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x "
+-		  "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
+-	prefix_entry->address.addr8[0], prefix_entry->address.addr8[1],
+-	prefix_entry->address.addr8[2], prefix_entry->address.addr8[3],
+-	prefix_entry->address.addr8[4], prefix_entry->address.addr8[5],
+-	prefix_entry->address.addr8[6], prefix_entry->address.addr8[7],
+-	prefix_entry->address.addr8[8], prefix_entry->address.addr8[9],
+-	prefix_entry->address.addr8[10], prefix_entry->address.addr8[11],
+-	prefix_entry->address.addr8[12], prefix_entry->address.addr8[13],
+-	prefix_entry->address.addr8[14], prefix_entry->address.addr8[15]);
++	memcpy((char __FAR__*)&prefix_entry->address,
++	       (char __FAR__*)ipv6_addr, sizeof(IPV6_ADDR));
++
++	inet_ntop(AF_INET6, &prefix_entry->address.addr8, addr_str,
++		  sizeof(addr_str));
++
++	LOG_DEBUG("IPv6: add prefix IP addr %s", addr_str);
+  
+ 	/* Put it on the list on head of the list. */
+ 	if (ipv6_context->addr_list != NULL) {
+@@ -419,7 +416,7 @@ int ipv6_discover_address(pIPV6_CONTEXT ipv6_context)
+ 	       sizeof(IPV6_ADDR));
+ 
+ 	icmp->icmpv6_cksum = 0;
+-	LOG_DEBUG("IPV6: Send rtr sol");
++	LOG_DEBUG("IPv6: Send rtr sol");
+ 	ipv6_send(ipv6_context, (u8_t *) icmp - (u8_t *) eth +
+ 		  sizeof(ICMPV6_HDR) + sizeof(ICMPV6_OPT_LINK_ADDR));
+ 	return rc;
+@@ -650,7 +647,7 @@ STATIC void ipv6_update_arp_table(pIPV6_CONTEXT ipv6_context,
+ 	int i;
+ 	pIPV6_ARP_ENTRY ipv6_arp_table = ipv6_context->ipv6_arp_table;
+ 
+-	LOG_DEBUG("IPV6: ARP update");
++	LOG_DEBUG("IPv6: Neighbor update");
+ 	/* 
+ 	 * Walk through the ARP mapping table and try to find an entry to
+ 	 * update. If none is found, the IP -> MAC address mapping is
+@@ -710,6 +707,7 @@ int ipv6_send_nd_solicited_packet(pIPV6_CONTEXT ipv6_context, pETH_HDR eth,
+ 	pICMPV6_HDR icmp;
+ 	int pkt_len = 0;
+ 	pIPV6_ADDR longest_match_addr;
++	char addr_str[INET6_ADDRSTRLEN];
+ 
+ 	ipv6->ipv6_nxt_hdr = IPPROTO_ICMPV6;
+ 
+@@ -719,7 +717,7 @@ int ipv6_send_nd_solicited_packet(pIPV6_CONTEXT ipv6_context, pETH_HDR eth,
+ 	/* Use Link-local as source address */
+ 	if (ipv6_is_it_our_link_local_address(ipv6_context, &ipv6->ipv6_dst) ==
+ 	    TRUE) {
+-		LOG_DEBUG("IPV6: NS using link local");
++		LOG_DEBUG("IPv6: NS using link local");
+ 		memcpy((char __FAR__ *)&ipv6->ipv6_src,
+ 		       (char __FAR__ *)&ipv6_context->link_local_addr,
+ 		       sizeof(IPV6_ADDR));
+@@ -727,12 +725,12 @@ int ipv6_send_nd_solicited_packet(pIPV6_CONTEXT ipv6_context, pETH_HDR eth,
+ 		longest_match_addr =
+ 		    ipv6_find_longest_match(ipv6_context, &ipv6->ipv6_dst);
+ 		if (longest_match_addr) {
+-			LOG_DEBUG("IPV6: NS using longest match addr");
++			LOG_DEBUG("IPv6: NS using longest match addr");
+ 			memcpy((char __FAR__ *)&ipv6->ipv6_src,  
+ 			       (char __FAR__ *)longest_match_addr,
+ 			       sizeof(IPV6_ADDR));
+ 		} else {
+-			LOG_DEBUG("IPV6: NS using link local instead");
++			LOG_DEBUG("IPv6: NS using link local instead");
+ 			memcpy((char __FAR__ *)&ipv6->ipv6_src,  
+ 			       (char __FAR__ *)&ipv6_context->link_local_addr,
+ 			       sizeof(IPV6_ADDR));
+@@ -740,17 +738,8 @@ int ipv6_send_nd_solicited_packet(pIPV6_CONTEXT ipv6_context, pETH_HDR eth,
+ 	}
+ 	icmp = (pICMPV6_HDR) ((u8_t *) ipv6 + sizeof(IPV6_HDR));
+ 
+-	LOG_DEBUG
+-	    ("IPV6: NS host ip addr %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
+-	     " %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
+-	     ipv6->ipv6_src.addr8[0], ipv6->ipv6_src.addr8[1],
+-	     ipv6->ipv6_src.addr8[2], ipv6->ipv6_src.addr8[3],
+-	     ipv6->ipv6_src.addr8[4], ipv6->ipv6_src.addr8[5],
+-	     ipv6->ipv6_src.addr8[6], ipv6->ipv6_src.addr8[7],
+-	     ipv6->ipv6_src.addr8[8], ipv6->ipv6_src.addr8[9],
+-	     ipv6->ipv6_src.addr8[10], ipv6->ipv6_src.addr8[11],
+-	     ipv6->ipv6_src.addr8[12], ipv6->ipv6_src.addr8[13],
+-	     ipv6->ipv6_src.addr8[14], ipv6->ipv6_src.addr8[15]);
++	inet_ntop(AF_INET6, &ipv6->ipv6_src.addr8, addr_str, sizeof(addr_str));
++	LOG_DEBUG("IPv6: NS host IP addr: %s", addr_str);
+ 	/* 
+ 	 * Destination IP address to be resolved is after the ICMPv6 
+ 	 * header.
+@@ -839,6 +828,7 @@ STATIC void ipv6_icmp_handle_router_adv(pIPV6_CONTEXT ipv6_context)
+ 	pICMPV6_OPT_HDR icmp_opt;
+ 	u16_t opt_len;
+ 	u16_t len;
++	char addr_str[INET6_ADDRSTRLEN];
+ 
+ 	if (ipv6_context->flags & IPV6_FLAGS_ROUTER_ADV_RECEIVED)
+ 		return;
+@@ -868,7 +858,7 @@ STATIC void ipv6_icmp_handle_router_adv(pIPV6_CONTEXT ipv6_context)
+ 	}
+ 
+ 	if (ipv6_context->flags & IPV6_FLAGS_ROUTER_ADV_RECEIVED) {
+-		LOG_DEBUG("IPV6: RTR ADV nd_ra_flags=0x%x",
++		LOG_DEBUG("IPv6: RTR ADV nd_ra_flags = 0x%x",
+ 			  icmp->nd_ra_flags_reserved);
+ 		if (icmp->nd_ra_curhoplimit > 0)
+ 			ipv6_context->hop_limit = icmp->nd_ra_curhoplimit;
+@@ -880,21 +870,17 @@ STATIC void ipv6_icmp_handle_router_adv(pIPV6_CONTEXT ipv6_context)
+ 			ipv6_context->flags |= IPV6_FLAGS_OTHER_STATEFUL_CONFIG;
+ 
+ 		if (icmp->nd_ra_router_lifetime != 0) {
+-			/* This is a default router. */
+-			memcpy((char __FAR__ *)&ipv6_context->default_router,
+-			       (char __FAR__ *)&ipv6->ipv6_src,
+-			       sizeof(IPV6_ADDR));
+-			LOG_DEBUG("IPV6: def router "
+-				  "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x "
+-				  "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
+-			ipv6->ipv6_src.addr8[0], ipv6->ipv6_src.addr8[1],
+-			ipv6->ipv6_src.addr8[2], ipv6->ipv6_src.addr8[3],
+-			ipv6->ipv6_src.addr8[4], ipv6->ipv6_src.addr8[5],
+-			ipv6->ipv6_src.addr8[6], ipv6->ipv6_src.addr8[7],
+-			ipv6->ipv6_src.addr8[8], ipv6->ipv6_src.addr8[9],
+-			ipv6->ipv6_src.addr8[10], ipv6->ipv6_src.addr8[11],
+-			ipv6->ipv6_src.addr8[12], ipv6->ipv6_src.addr8[13],
+-			ipv6->ipv6_src.addr8[14], ipv6->ipv6_src.addr8[15]);
++			/* There is a default router. */
++			if (ipv6_context->ustack->router_autocfg !=
++			    IPV6_RTR_AUTOCFG_OFF)
++				memcpy(
++				   (char __FAR__*)&ipv6_context->default_router,
++				       (char __FAR__*)&ipv6->ipv6_src,
++				       sizeof(IPV6_ADDR));
++			inet_ntop(AF_INET6, &ipv6_context->default_router,
++				  addr_str, sizeof(addr_str));
++			LOG_DEBUG("IPV6: Got default router IP addr: %s",
++				  addr_str);
+ 		}
+ 	}
+ }
+@@ -903,6 +889,7 @@ STATIC void ipv6_icmp_process_prefix(pIPV6_CONTEXT ipv6_context,
+ 				     pICMPV6_OPT_PREFIX icmp_prefix)
+ {
+ 	IPV6_ADDR addr;
++	char addr_str[INET6_ADDRSTRLEN];
+ 
+ 	/* we only process on-link address info */
+ 	if (!(icmp_prefix->flags & ICMPV6_OPT_PREFIX_FLAG_ON_LINK))
+@@ -917,6 +904,8 @@ STATIC void ipv6_icmp_process_prefix(pIPV6_CONTEXT ipv6_context,
+ 		       (char __FAR__ *)&icmp_prefix->prefix, 8);
+ 		memcpy((char __FAR__ *)&addr.addr8[8],
+ 		       &ipv6_context->link_local_addr.addr8[8], 8);
++		inet_ntop(AF_INET6, &addr, addr_str, sizeof(addr_str));
++		LOG_DEBUG("IPv6: Got RA ICMP option IP addr: %s", addr_str);
+ 		ipv6_add_prefix_entry(ipv6_context, &addr, 64);
+ 	}
+ }
+@@ -929,11 +918,12 @@ STATIC void ipv6_icmp_handle_nd_adv(pIPV6_CONTEXT ipv6_context)
+ 	pICMPV6_OPT_LINK_ADDR link_opt = (pICMPV6_OPT_LINK_ADDR)((u8_t *)icmp +
+ 					sizeof(ICMPV6_HDR) + sizeof(IPV6_ADDR));
+ 	pIPV6_ADDR tar_addr6;
++	char addr_str[INET6_ADDRSTRLEN];
+ 
+ 	/* Added the multicast check for ARP table update */
+ 	/* Should we qualify for only our host's multicast and our
+ 	   link_local_multicast?? */
+-	LOG_DEBUG("IPV6: Handle nd adv");
++	LOG_DEBUG("IPv6: Handle nd adv");
+ 	if ((ipv6_is_it_our_address(ipv6_context, &ipv6->ipv6_dst) == TRUE) ||
+ 	    (memcmp((char __FAR__ *)&ipv6_context->link_local_multi,
+ 		    (char __FAR__ *)&ipv6->ipv6_dst, sizeof(IPV6_ADDR)) == 0) ||
+@@ -951,21 +941,14 @@ STATIC void ipv6_icmp_handle_nd_adv(pIPV6_CONTEXT ipv6_context)
+ 		if (link_opt->hdr.type == IPV6_ICMP_OPTION_TAR_ADDR) {
+ 			tar_addr6 = (pIPV6_ADDR)((u8_t *)icmp +
+ 				    sizeof(ICMPV6_HDR));
+-			LOG_DEBUG("IPV6: tar mac %x:%x:%x:%x:%x:%x",
++			LOG_DEBUG("IPV6: Target MAC "
++				  "%02x:%02x:%02x:%02x:%02x:%02x",
+ 				link_opt->link_addr[0], link_opt->link_addr[1],
+ 				link_opt->link_addr[2], link_opt->link_addr[3],
+ 				link_opt->link_addr[4], link_opt->link_addr[5]);
+-			LOG_DEBUG("IPV6: tar addr "
+-				  "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x "
+-				  "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
+-				  tar_addr6->addr8[0], tar_addr6->addr8[1],
+-				  tar_addr6->addr8[2], tar_addr6->addr8[3],
+-				  tar_addr6->addr8[4], tar_addr6->addr8[5],
+-				  tar_addr6->addr8[6], tar_addr6->addr8[7],
+-				  tar_addr6->addr8[8], tar_addr6->addr8[9],
+-				  tar_addr6->addr8[10], tar_addr6->addr8[11],
+-				  tar_addr6->addr8[12], tar_addr6->addr8[13],
+-				  tar_addr6->addr8[14], tar_addr6->addr8[15]);
++			inet_ntop(AF_INET6, &tar_addr6->addr8, addr_str,
++				  sizeof(addr_str));
++			LOG_DEBUG("IPv6: Target IP addr %s", addr_str);
+ 			ipv6_update_arp_table(ipv6_context, tar_addr6,
+ 					      (MAC_ADDR *)link_opt->link_addr);
+ 		}
+@@ -985,14 +968,15 @@ STATIC void ipv6_icmp_handle_nd_sol(pIPV6_CONTEXT ipv6_context)
+ 	pIPV6_ADDR longest_match_addr;
+ 	pIPV6_ADDR tar_addr6;
+ 
+-	LOG_DEBUG("IPV6: Handle nd sol");
++	LOG_DEBUG("IPv6: Handle nd sol");
+ 
+ 	if ((memcmp((char __FAR__ *)&ipv6_context->mac_addr,
+ 		    (char __FAR__ *)eth->dest_mac, sizeof(MAC_ADDR)) != 0) &&
+ 	    (iscsiL2IsOurMcAddr(ipv6_context, (pMAC_ADDRESS) & eth->dest_mac) ==
+ 	     FALSE)) {
+ 		/* This packet is not for us to handle */
+-		LOG_DEBUG("IPV6: MAC not addressed to us %x:%x:%x:%x:%x:%x",
++		LOG_DEBUG("IPv6: MAC not addressed to us "
++			  "%02x:%02x:%02x:%02x:%02x:%02x",
+ 			  eth->dest_mac[0], eth->dest_mac[1],
+ 			  eth->dest_mac[2], eth->dest_mac[3],
+ 			  eth->dest_mac[4], eth->dest_mac[5]);
+@@ -1005,7 +989,7 @@ STATIC void ipv6_icmp_handle_nd_sol(pIPV6_CONTEXT ipv6_context)
+ 						  sizeof(ICMPV6_HDR)))
+ 	    == FALSE) {
+ 		/* This packet is not for us to handle */
+-		LOG_DEBUG("IPV6: IP not addressed to us");
++		LOG_DEBUG("IPv6: IP not addressed to us");
+ 		return;
+ 	}
+ 
+@@ -1026,7 +1010,7 @@ STATIC void ipv6_icmp_handle_nd_sol(pIPV6_CONTEXT ipv6_context)
+ 		tar_addr6 = (pIPV6_ADDR)((u8_t *)icmp + sizeof(ICMPV6_HDR));
+ 		if (ipv6_is_it_our_link_local_address(ipv6_context, tar_addr6)
+ 		    == TRUE) {
+-			LOG_DEBUG("IPV6: NA using link local");
++			LOG_DEBUG("IPv6: NA using link local");
+ 			memcpy((char __FAR__ *)&ipv6->ipv6_src,  
+ 			       (char __FAR__ *)&ipv6_context->link_local_addr,
+ 			       sizeof(IPV6_ADDR));
+@@ -1034,12 +1018,12 @@ STATIC void ipv6_icmp_handle_nd_sol(pIPV6_CONTEXT ipv6_context)
+ 			longest_match_addr =
+ 			      ipv6_find_longest_match(ipv6_context, tar_addr6);
+ 			if (longest_match_addr) {
+-				LOG_DEBUG("IPV6: NA using longest match addr");
++				LOG_DEBUG("IPv6: NA using longest match addr");
+ 				memcpy((char __FAR__ *)&ipv6->ipv6_src,  
+ 				       (char __FAR__ *)longest_match_addr,
+ 				       sizeof(IPV6_ADDR));
+ 			} else {
+-				LOG_DEBUG("IPV6: NA using link local instead");
++				LOG_DEBUG("IPv6: NA using link local instead");
+ 				memcpy((char __FAR__ *)&ipv6->ipv6_src,  
+ 				(char __FAR__ *)&ipv6_context->link_local_addr,
+ 				       sizeof(IPV6_ADDR));
+@@ -1047,7 +1031,7 @@ STATIC void ipv6_icmp_handle_nd_sol(pIPV6_CONTEXT ipv6_context)
+ 		}
+ 	} else {
+ 		/* No target link address, just use whatever it sent to us */
+-		LOG_DEBUG("IPV6: NA use dst addr");
++		LOG_DEBUG("IPv6: NA use dst addr");
+ 		memcpy((char __FAR__ *)&ipv6->ipv6_src,
+ 		       (char __FAR__ *)&tmp,
+ 		       sizeof(IPV6_ADDR));
+@@ -1085,7 +1069,7 @@ STATIC void ipv6_icmp_handle_nd_sol(pIPV6_CONTEXT ipv6_context)
+ */
+ 	ipv6->ipv6_plen = HOST_TO_NET16((sizeof(ICMPV6_HDR) +
+ 					 icmpv6_opt_len + sizeof(IPV6_ADDR)));
+-	LOG_DEBUG("IPV6: Send nd adv");
++	LOG_DEBUG("IPv6: Send nd adv");
+ 	ipv6_send(ipv6_context,
+ 		  (u8_t *) icmp - (u8_t *) eth +
+ 		  sizeof(ICMPV6_HDR) +
+@@ -1118,7 +1102,7 @@ STATIC void ipv6_icmp_handle_echo_request(pIPV6_CONTEXT ipv6_context)
+ 	icmp->icmpv6_type = ICMPV6_ECHO_REPLY;
+ 	icmp->icmpv6_code = 0;
+ 	icmp->icmpv6_cksum = 0;
+-	LOG_DEBUG("IPV6: Send echo reply");
++	LOG_DEBUG("IPv6: Send echo reply");
+ 	ipv6_send(ipv6_context, (u8_t *) icmp - (u8_t *) eth +
+ 		  sizeof(IPV6_HDR) + HOST_TO_NET16(ipv6->ipv6_plen));
+ 	return;
+@@ -1126,7 +1110,8 @@ STATIC void ipv6_icmp_handle_echo_request(pIPV6_CONTEXT ipv6_context)
+ 
+ void ipv6_set_ip_params(pIPV6_CONTEXT ipv6_context,
+ 			pIPV6_ADDR src_ip, u8_t prefix_len,
+-			pIPV6_ADDR default_gateway)
++			pIPV6_ADDR default_gateway,
++			pIPV6_ADDR linklocal)
+ {
+ 	if (!(IPV6_IS_ADDR_UNSPECIFIED(src_ip))) {
+ 		ipv6_add_prefix_entry(ipv6_context, src_ip, prefix_len);
+@@ -1146,9 +1131,30 @@ void ipv6_set_ip_params(pIPV6_CONTEXT ipv6_context,
+ 	}
+ 
+ 	if (!(IPV6_IS_ADDR_UNSPECIFIED(default_gateway))) {
+-		/* This is a default router. */
+-		memcpy((char __FAR__ *)&ipv6_context->default_router,
+-		       (char __FAR__ *)default_gateway, sizeof(IPV6_ADDR));
++		/* Override the default gateway addr */
++		memcpy((char __FAR__*)&ipv6_context->default_router,
++		       (char __FAR__*)default_gateway, sizeof(IPV6_ADDR));
++		ipv6_add_prefix_entry(ipv6_context, default_gateway,
++				      prefix_len);
++	}
++	if (!(IPV6_IS_ADDR_UNSPECIFIED(linklocal))) {
++		/* Override the linklocal addr */
++		memcpy((char __FAR__*)&ipv6_context->link_local_addr,
++		       (char __FAR__*)linklocal, sizeof(IPV6_ADDR));
++		ipv6_context->link_local_multi.addr8[0] = 0xff;
++		ipv6_context->link_local_multi.addr8[1] = 0x02;
++		ipv6_context->link_local_multi.addr8[11] = 0x01;
++		ipv6_context->link_local_multi.addr8[12] = 0xff;
++		ipv6_context->link_local_multi.addr8[13] |=
++		    ipv6_context->link_local_addr.addr8[13];
++		ipv6_context->link_local_multi.addr16[7] =
++		    ipv6_context->link_local_addr.addr16[7];
++
++		/* Default Prefix length is 64 */
++		/* Add Link local address to the head of the ipv6 address
++		   list */
++		ipv6_add_prefix_entry(ipv6_context,
++				      &ipv6_context->link_local_addr, 64);
+ 	}
+ }
+ 
+@@ -1220,7 +1226,7 @@ u16_t ipv6_do_stateful_dhcpv6(pIPV6_CONTEXT ipv6_context, u32_t flags)
+ 	    (IPV6_FLAGS_MANAGED_ADDR_CONFIG | IPV6_FLAGS_OTHER_STATEFUL_CONFIG);
+ 
+ 	if (!(ipv6_context->flags & IPV6_FLAGS_ROUTER_ADV_RECEIVED)) {
+-		LOG_DEBUG("IPV6: There is no IPv6 router on the network");
++		LOG_DEBUG("IPv6: There is no IPv6 router on the network");
+ 		ra_flags |=
+ 		    (IPV6_FLAGS_MANAGED_ADDR_CONFIG |
+ 		     IPV6_FLAGS_OTHER_STATEFUL_CONFIG);
+@@ -1234,7 +1240,7 @@ u16_t ipv6_do_stateful_dhcpv6(pIPV6_CONTEXT ipv6_context, u32_t flags)
+ 	    (ra_flags & IPV6_FLAGS_OTHER_STATEFUL_CONFIG))
+ 		task |= DHCPV6_TASK_GET_OTHER_PARAMS;
+ 
+-	LOG_DEBUG("IPV6: Stateful flags=0x%x, ra_flags=0x%x, task=0x%x", flags,
++	LOG_DEBUG("IPv6: Stateful flags=0x%x, ra_flags=0x%x, task=0x%x", flags,
+ 		  ra_flags, task);
+ 
+ 	return task;
+diff --git a/src/uip/ipv6.h b/src/uip/ipv6.h
+index 167f5f6..ed2f3a4 100644
+--- a/src/uip/ipv6.h
++++ b/src/uip/ipv6.h
+@@ -343,7 +343,8 @@ int ipv6_add_prefix_entry(pIPV6_CONTEXT ipv6_context,
+ 			  IPV6_ADDR * ipv6_addr, u8_t prefix_len);
+ void ipv6_set_ip_params(pIPV6_CONTEXT ipv6_context,
+ 			pIPV6_ADDR src_ip, u8_t prefix_len,
+-			pIPV6_ADDR default_gateway);
++			pIPV6_ADDR default_gateway,
++			pIPV6_ADDR linklocal);
+ void ipv6_set_host_addr(pIPV6_CONTEXT ipv6_context, pIPV6_ADDR src_ip);
+ int ipv6_get_default_router_ip_addrs(pIPV6_CONTEXT ipv6_context,
+ 				     pIPV6_ADDR ip_addr);
+diff --git a/src/uip/ipv6_ndpc.c b/src/uip/ipv6_ndpc.c
+index 6d101ce..89dbd5e 100644
+--- a/src/uip/ipv6_ndpc.c
++++ b/src/uip/ipv6_ndpc.c
+@@ -65,6 +65,7 @@ static PT_THREAD(handle_ndp(struct uip_stack *ustack, int force))
+ 	pIPV6_CONTEXT ipv6c;
+ 	pDHCPV6_CONTEXT dhcpv6c = NULL;
+ 	u16_t task = 0;
++	char buf[INET6_ADDRSTRLEN];
+ 
+ 	s = ustack->ndpc;
+ 	if (s == NULL) {
+@@ -86,6 +87,9 @@ static PT_THREAD(handle_ndp(struct uip_stack *ustack, int force))
+ 	if (s->state == NDPC_STATE_RTR_ADV)
+ 		goto rtr_adv;
+ 
++	/* For AUTOCFG == DHCPv6, do all
++	   For         == ND, skip DHCP only and do RTR
++	   For         == UNUSED/UNSPEC, do all as according to DHCP or not */
+ 	s->state = NDPC_STATE_RTR_SOL;
+ 	/* try_again: */
+ 	s->ticks = CLOCK_SECOND * IPV6_MAX_ROUTER_SOL_DELAY;
+@@ -97,7 +101,7 @@ static PT_THREAD(handle_ndp(struct uip_stack *ustack, int force))
+ 		ipv6_autoconfig(s->ipv6_context);
+ 
+ 		timer_set(&s->timer, s->ticks);
+-	      wait_rtr:
++wait_rtr:
+ 		s->ustack->uip_flags &= ~UIP_NEWDATA;
+ 		LOG_DEBUG("%s: ndpc_handle wait for rtr adv flags=0x%x",
+ 			  s->nic->log_name, ipv6c->flags);
+@@ -134,10 +138,12 @@ no_rtr_adv:
+ 	s->state = NDPC_STATE_RTR_ADV;
+ 
+ rtr_adv:
+-	/* Both Static IPv6 and DHCPv6 comes here */
++	if (!(ustack->ip_config & IPV6_CONFIG_DHCP))
++		goto staticv6;
+ 
++	/* Only DHCPv6 comes here */
+ 	task = ipv6_do_stateful_dhcpv6(ipv6c, ISCSI_FLAGS_DHCP_TCPIP_CONFIG);
+-	if (task && (ustack->ip_config == IPV6_CONFIG_DHCP)) {
++	if (task) {
+ 		/* Run the DHCPv6 engine */
+ 
+ 		if (!dhcpv6c)
+@@ -187,6 +193,7 @@ wait_dhcp:
+ 			}
+ 		} while (dhcpv6c->dhcpv6_done == FALSE);
+ 		s->state = NDPC_STATE_DHCPV6_DONE;
++
+ 		LOG_DEBUG("%s: ndpc_handle got dhcpv6", s->nic->log_name);
+ 
+ 		/* End of DHCPv6 engine */
+@@ -197,28 +204,25 @@ wait_dhcp:
+ 				  s->nic->log_name);
+ 			PT_RESTART(&s->pt);
+ 		}
+-		IPV6_ADDR tmp, tmp2;
+-		char buf[INET6_ADDRSTRLEN];
+-
++staticv6:
+ 		ipv6_disable_dhcpv6(ipv6c);
+-		memcpy(&tmp.addr8, &ustack->hostaddr6, sizeof(IPV6_ADDR));
+-		LOG_DEBUG("%s: host ip addr %02x:%02x:%02x:%02x:%02x:%02x:"
+-			  "%02x:%02x", s->nic->log_name,
+-		     ustack->hostaddr6[0], ustack->hostaddr6[1],
+-		     ustack->hostaddr6[2], ustack->hostaddr6[3],
+-		     ustack->hostaddr6[4], ustack->hostaddr6[5],
+-		     ustack->hostaddr6[6], ustack->hostaddr6[7]);
+-		memset(&tmp2, 0, sizeof(tmp2));
+-		ipv6_set_ip_params(ipv6c, &tmp,
+-				   ustack->prefix_len, &tmp2);
+-
+-		ipv6_add_solit_node_address(ipv6c, &tmp);
+-
+-		inet_ntop(AF_INET6, &tmp.addr8, buf, sizeof(buf));
+-		LOG_INFO("%s: Static hostaddr IP: %s", s->nic->log_name,
+-			 buf);
+-
+ 	}
++	/* Copy out the default_router_addr6 and ll */
++	if (ustack->router_autocfg != IPV6_RTR_AUTOCFG_OFF)
++		memcpy(&ustack->default_route_addr6,
++		       &ipv6c->default_router, sizeof(IPV6_ADDR));
++	inet_ntop(AF_INET6, &ustack->default_route_addr6,
++		  buf, sizeof(buf));
++	LOG_INFO("%s: Default router IP: %s", s->nic->log_name,
++		 buf);
++
++	if (ustack->linklocal_autocfg != IPV6_LL_AUTOCFG_OFF)
++		memcpy(&ustack->linklocal6, &ipv6c->link_local_addr,
++		       sizeof(IPV6_ADDR));
++	inet_ntop(AF_INET6, &ustack->linklocal6,
++		  buf, sizeof(buf));
++	LOG_INFO("%s: Linklocal IP: %s", s->nic->log_name,
++		 buf);
+ 
+ ipv6_loop:
+ 	s->state = NDPC_STATE_BACKGROUND_LOOP;
+@@ -249,6 +253,8 @@ int ndpc_init(nic_t * nic, struct uip_stack *ustack,
+ 	pIPV6_CONTEXT ipv6c;
+ 	pDHCPV6_CONTEXT dhcpv6c;
+ 	struct ndpc_state *s = ustack->ndpc;
++	IPV6_ADDR src, gw, ll;
++	char buf[INET6_ADDRSTRLEN];
+ 
+ 	if (s) {
+ 		LOG_DEBUG("NDP: NDP context already allocated");
+@@ -315,9 +321,30 @@ init2:
+ 
+ 	if (ustack->ip_config == IPV6_CONFIG_DHCP) {
+ 		/* DHCPv6 specific */
++		memset(&src, 0, sizeof(src));
+ 	} else {
+ 		/* Static v6 specific */
++		memcpy(&src.addr8, &ustack->hostaddr6, sizeof(IPV6_ADDR));
++		ipv6_add_solit_node_address(ipv6c, &src);
++
++		inet_ntop(AF_INET6, &src.addr8, buf, sizeof(buf));
++		LOG_INFO("%s: Static hostaddr IP: %s", s->nic->log_name,
++			 buf);
+ 	}
++	/* Copy out the default_router_addr6 and ll */
++	if (ustack->router_autocfg == IPV6_RTR_AUTOCFG_OFF)
++		memcpy(&gw.addr8, &ustack->default_route_addr6,
++		       sizeof(IPV6_ADDR));
++	else
++		memset(&gw, 0, sizeof(gw));
++
++	if (ustack->linklocal_autocfg == IPV6_LL_AUTOCFG_OFF)
++		memcpy(&ll.addr8, &ustack->linklocal6,
++		       sizeof(IPV6_ADDR));
++	else
++		memset(&ll, 0, sizeof(ll));
++	ipv6_set_ip_params(ipv6c, &src,
++			   ustack->prefix_len, &gw, &ll);
+ 
+ 	return 0;
+ error2:
+@@ -367,16 +394,14 @@ int ndpc_request(struct uip_stack *ustack, void *in, void *out, int request)
+ 	//LOG_DEBUG("%s: NDP - Request %d", s->nic->log_name, request);
+ 
+ 	while (s->state != NDPC_STATE_BACKGROUND_LOOP) {
+-		LOG_DEBUG("%s: ndpc state not in background loop, run handler",
+-			  s->nic->log_name);
++		LOG_DEBUG("%s: ndpc state not in background loop, run handler ",
++			  "request = %d", s->nic->log_name, request);
+ 		handle_ndp(ustack, 1);
+ 	}
+ 
+ 	ipv6c = s->ipv6_context;
+ 	switch (request) {
+ 	case NEIGHBOR_SOLICIT:
+-		LOG_DEBUG("nd sol: in=%p in->eth=%p in->ipv6=%p", in, in,
+-			  (u8_t *) in + 4);
+ 		*(int *)out = ipv6_send_nd_solicited_packet(ipv6c,
+ 					  (pETH_HDR) ((pNDPC_REQPTR)in)->eth,
+ 					  (pIPV6_HDR) ((pNDPC_REQPTR)in)->ipv6);
+@@ -385,12 +410,6 @@ int ndpc_request(struct uip_stack *ustack, void *in, void *out, int request)
+ 		*(int *)out = ipv6_is_it_our_link_local_address(ipv6c,
+ 								(pIPV6_ADDR)in);
+ 		break;
+-	case GET_LINK_LOCAL_ADDR:
+-		*(pIPV6_ADDR *) out = &ipv6c->link_local_addr;
+-		break;
+-	case GET_DEFAULT_ROUTER_ADDR:
+-		*(pIPV6_ADDR *)out = &ipv6c->default_router;
+-		break;
+ 	case CHECK_ARP_TABLE:
+ 		*(int *)out = ipv6_ip_in_arp_table(ipv6c,
+ 				   (pIPV6_ADDR) ((pNDPC_REQPTR)in)->ipv6,
+@@ -399,7 +418,9 @@ int ndpc_request(struct uip_stack *ustack, void *in, void *out, int request)
+ 	case GET_HOST_ADDR:
+ 		*(pIPV6_ADDR *)out = ipv6_find_longest_match(ipv6c,
+ 							     (pIPV6_ADDR)in);
++		break;
+ 	default:
++		ret = -EINVAL;
+ 		break;
+ 	}
+ 	return ret;
+diff --git a/src/uip/uip.c b/src/uip/uip.c
+index 9c79e07..d03b92e 100644
+--- a/src/uip/uip.c
++++ b/src/uip/uip.c
+@@ -1403,8 +1403,6 @@ void uip_process(struct uip_stack *ustack, u8_t flag)
+ #endif /* UIP_UDP */
+ 
+ 		/* This is IPv6 ICMPv6 processing code. */
+-		LOG_DEBUG(PFX "icmp6_input: length %d", ustack->uip_len);
+-
+ 		if (ipv6_hdr->ip6_nxt != UIP_PROTO_ICMP6) {
+ 			/* We only allow ICMPv6 packets from here. */
+ 			++ustack->stats.ip.drop;
+@@ -2344,7 +2342,7 @@ tcp_send:
+ 		uip_ip6addr_copy(IPv6_BUF(ustack)->srcipaddr,
+ 				 ustack->hostaddr6);
+ 		uip_ip6addr_copy(IPv6_BUF(ustack)->destipaddr,
+-				 uip_connr->ripaddr);
++				 uip_connr->ripaddr6);
+ 	} else {
+ 		tcp_ipv4_hdr->proto = UIP_PROTO_TCP;
+ 		uip_ip4addr_copy(tcp_ipv4_hdr->srcipaddr, ustack->hostaddr);
+diff --git a/src/uip/uip.h b/src/uip/uip.h
+index 2b5f88c..ccac680 100644
+--- a/src/uip/uip.h
++++ b/src/uip/uip.h
+@@ -1031,6 +1031,7 @@ extern u16_t uip_urglen, uip_surglen;
+  */
+ struct __attribute__ ((__packed__)) uip_conn {
+ 	uip_ip4addr_t ripaddr;
++	uip_ip6addr_t ripaddr6;
+ 			   /**< The IP address of the remote host. */
+ 
+ 	u16_t lport;  /**< The local TCP port, in network byte order. */
+@@ -1564,6 +1565,7 @@ struct uip_stack {
+ 				   a new connection. */
+ #endif				/* UIP_ACTIVE_OPEN */
+ 
++#define IP_CONFIG_OFF			0x00
+ #define IPV4_CONFIG_OFF			0x01
+ #define IPV4_CONFIG_STATIC		0x02
+ #define IPV4_CONFIG_DHCP		0x04
+@@ -1573,8 +1575,24 @@ struct uip_stack {
+ 	u8_t ip_config;
+ 
+ 	uip_ip4addr_t hostaddr, netmask, default_route_addr;
+-	uip_ip6addr_t hostaddr6, netmask6, default_route_addr6;
++	uip_ip6addr_t hostaddr6, netmask6, default_route_addr6,
++		      linklocal6;
+ 	int prefix_len;
++	u8_t ipv6_autocfg;
++#define IPV6_AUTOCFG_DHCPV6		(1<<0)
++#define IPV6_AUTOCFG_ND			(1<<1)
++#define IPV6_AUTOCFG_NOTSPEC		(1<<6)
++#define IPV6_AUTOCFG_NOTUSED		(1<<7)
++	u8_t linklocal_autocfg;
++#define IPV6_LL_AUTOCFG_ON		(1<<0)
++#define IPV6_LL_AUTOCFG_OFF		(1<<1)
++#define IPV6_LL_AUTOCFG_NOTSPEC		(1<<6)
++#define IPV6_LL_AUTOCFG_NOTUSED		(1<<7)
++	u8_t router_autocfg;
++#define IPV6_RTR_AUTOCFG_ON		(1<<0)
++#define IPV6_RTR_AUTOCFG_OFF		(1<<1)
++#define IPV6_RTR_AUTOCFG_NOTSPEC	(1<<6)
++#define IPV6_RTR_AUTOCFG_NOTUSED	(1<<7)
+ 
+ #define UIP_NEIGHBOR_ENTRIES 8
+ 	struct neighbor_entry neighbor_entries[UIP_NEIGHBOR_ENTRIES];
+@@ -1586,7 +1604,6 @@ struct uip_stack {
+ 	pthread_mutex_t lock;
+ 
+ 	/*  IPv6 support */
+-
+ #define UIP_SUPPORT_IPv6_ENABLED	0x01
+ #define UIP_SUPPORT_IPv6_DISABLED	0x02
+ 	u8_t enable_IPv6;
+diff --git a/src/uip/uip_arp.c b/src/uip/uip_arp.c
+index 321281c..3ef3b07 100644
+--- a/src/uip/uip_arp.c
++++ b/src/uip/uip_arp.c
+@@ -265,10 +265,14 @@ uip_arp_arpin(nic_interface_t * nic_iface,
+ 			arp->sipaddr[0] = ustack->hostaddr[0];
+ 			arp->sipaddr[1] = ustack->hostaddr[1];
+ 
+-			if (nic_iface->vlan_id == 0)
++			if (nic_iface->vlan_id == 0) {
+ 				eth->type = htons(UIP_ETHTYPE_ARP);
+-			else
++				pkt->buf_size = sizeof(*arp) + sizeof(*eth);
++			} else {
+ 				eth->type = htons(UIP_ETHTYPE_8021Q);
++				pkt->buf_size = sizeof(*arp) +
++						sizeof(struct uip_vlan_eth_hdr);
++			}
+ 			pkt->buf_size = sizeof(*arp) + sizeof(*eth);
+ 		}
+ 		break;
+diff --git a/src/unix/iscsid_ipc.c b/src/unix/iscsid_ipc.c
+index 6bc5c11..d7372fc 100644
+--- a/src/unix/iscsid_ipc.c
++++ b/src/unix/iscsid_ipc.c
+@@ -70,20 +70,34 @@ struct iscsid_options {
+ 	pthread_t thread;
+ };
+ 
+-struct ip_addr_mask {
+-	int ip_type;
+-	union {
+-		struct in_addr addr4;
+-		struct in6_addr addr6;
+-	} addr;
+-	union {
+-		struct in_addr nm4;
+-		struct in6_addr nm6;
+-	} netmask;
+-#define addr4		addr.addr4
+-#define addr6		addr.addr6
+-#define nm4		netmask.nm4
+-#define nm6		netmask.nm6
++struct iface_rec_decode {
++	/* General */
++	int32_t			iface_num;
++	uint32_t		ip_type;
++
++	/* IPv4 */
++	struct in_addr		ipv4_addr;
++	struct in_addr		ipv4_subnet_mask;
++	struct in_addr		ipv4_gateway;
++
++	/* IPv6 */
++	struct in6_addr		ipv6_addr;
++	struct in6_addr		ipv6_subnet_mask;
++	uint32_t		prefix_len;
++	struct in6_addr		ipv6_linklocal;
++	struct in6_addr		ipv6_router;
++
++	uint8_t			ipv6_autocfg;
++	uint8_t                 linklocal_autocfg;
++	uint8_t                 router_autocfg;
++
++	uint8_t			vlan_state;
++	uint8_t			vlan_priority;
++	uint16_t		vlan_id;
++
++#define MIN_MTU_SUPPORT		46
++#define MAX_MTU_SUPPORT		9000
++	uint16_t		mtu;
+ };
+ 
+ /******************************************************************************
+@@ -119,8 +133,7 @@ static void *enable_nic_thread(void *data)
+ 	pthread_exit(NULL);
+ }
+ 
+-static int decode_cidr(char *in_ipaddr_str, struct ip_addr_mask *ipam,
+-		       int *prefix_len)
++static int decode_cidr(char *in_ipaddr_str, struct iface_rec_decode *ird)
+ {
+ 	int rc = 0, i;
+ 	char *tmp, *tok;
+@@ -130,7 +143,6 @@ static int decode_cidr(char *in_ipaddr_str, struct ip_addr_mask *ipam,
+ 	struct in_addr ia;
+ 	struct in6_addr ia6;
+ 
+-	memset(ipam, 0, sizeof(struct ip_addr_mask));
+ 	if (strlen(in_ipaddr_str) > NI_MAXHOST)
+ 		strncpy(ipaddr_str, in_ipaddr_str, NI_MAXHOST);
+ 	else
+@@ -149,16 +161,16 @@ static int decode_cidr(char *in_ipaddr_str, struct ip_addr_mask *ipam,
+ 
+ 	/*  Determine if the IP address passed from the iface file is
+ 	 *  an IPv4 or IPv6 address */
+-	rc = inet_pton(AF_INET, ipaddr_str, &ipam->addr6);
++	rc = inet_pton(AF_INET, ipaddr_str, &ird->ipv6_addr);
+ 	if (rc == 0) {
+ 		/* Test to determine if the addres is an IPv6 address */
+-		rc = inet_pton(AF_INET6, ipaddr_str, &ipam->addr6);
++		rc = inet_pton(AF_INET6, ipaddr_str, &ird->ipv6_addr);
+ 		if (rc == 0) {
+ 			LOG_ERR(PFX "Could not parse IP address: '%s'",
+ 				ipaddr_str);
+ 			goto out;
+ 		}
+-		ipam->ip_type = AF_INET6;
++		ird->ip_type = AF_INET6;
+ 		if (keepbits > 128) {
+ 			LOG_ERR(PFX "CIDR netmask > 128 for IPv6: %d(%s)",
+ 				keepbits, tmp);
+@@ -166,15 +178,15 @@ static int decode_cidr(char *in_ipaddr_str, struct ip_addr_mask *ipam,
+ 		}
+ 		if (!keepbits) {
+ 			/* Default prefix mask to 64 */
+-			memcpy(&ipam->nm6.s6_addr, all_zeroes_addr6,
++			memcpy(&ird->ipv6_subnet_mask.s6_addr, all_zeroes_addr6,
+ 			       sizeof(struct in6_addr));
++			ird->prefix_len = 64;
+ 			for (i = 0; i < 2; i++)
+-				ipam->nm6.s6_addr32[i] = 0xffffffff;
++				ird->ipv6_subnet_mask.s6_addr32[i] = 0xffffffff;
+ 			goto out;
+ 		}
+-		*prefix_len = keepbits;
+-		memcpy(&ia6.s6_addr, all_zeroes_addr6,
+-		       sizeof(struct in6_addr));
++		ird->prefix_len = keepbits;
++		memcpy(&ia6.s6_addr, all_zeroes_addr6, sizeof(struct in6_addr));
+ 		for (i = 0; i < 4; i++) {
+ 			if (keepbits < 32) {
+ 				ia6.s6_addr32[i] = keepbits > 0 ?
+@@ -184,12 +196,12 @@ static int decode_cidr(char *in_ipaddr_str, struct ip_addr_mask *ipam,
+ 				ia6.s6_addr32[i] = 0xFFFFFFFF;
+ 			keepbits -= 32;
+ 		}
+-		ipam->nm6 = ia6;
++		ird->ipv6_subnet_mask = ia6;
+ 		if (inet_ntop(AF_INET6, &ia6, str, sizeof(str)))
+ 			LOG_INFO(PFX "Using netmask: %s", str);
+ 	} else {
+-		ipam->ip_type = AF_INET;
+-		rc = inet_pton(AF_INET, ipaddr_str, &ipam->addr4);
++		ird->ip_type = AF_INET;
++		rc = inet_pton(AF_INET, ipaddr_str, &ird->ipv4_addr);
+ 
+ 		if (keepbits > 32) {
+ 			LOG_ERR(PFX "CIDR netmask > 32 for IPv4: %d(%s)",
+@@ -197,54 +209,153 @@ static int decode_cidr(char *in_ipaddr_str, struct ip_addr_mask *ipam,
+ 			goto out;
+ 		}
+ 		ia.s_addr = keepbits > 0 ? 0x00 - (1 << (32 - keepbits)) : 0;
+-		ipam->nm4.s_addr = htonl(ia.s_addr);
+-		LOG_INFO(PFX "Using netmask: %s", inet_ntoa(ipam->nm4));
++		ird->ipv4_subnet_mask.s_addr = htonl(ia.s_addr);
++		LOG_INFO(PFX "Using netmask: %s",
++			 inet_ntoa(ird->ipv4_subnet_mask));
+ 	}
+ out:
+ 	return rc;
+ }
+ 
++static int decode_iface(struct iface_rec_decode *ird, struct iface_rec *rec)
++{
++	int rc = 0;
++	char ipaddr_str[NI_MAXHOST];
++
++	/* Decodes the rec contents */
++	memset(ird, 0, sizeof(struct iface_rec_decode));
++
++	/*  Detect for CIDR notation and strip off the netmask if present */
++	rc = decode_cidr(rec->ipaddress, ird);
++	if (rc && !ird->ip_type) {
++		LOG_ERR(PFX "cidr decode err: rc=%d, ip_type=%d",
++			rc, ird->ip_type);
++		/* Can't decode address, just exit */
++		return rc;
++	}
++	rc = 0;
++
++	ird->iface_num = rec->iface_num;
++	ird->vlan_id = rec->vlan_id;
++	if (rec->iface_num != IFACE_NUM_INVALID) {
++		ird->mtu = rec->mtu;
++		if (rec->vlan_id && strcmp(rec->vlan_state, "disable")) {
++			ird->vlan_state = 1;
++			ird->vlan_priority = rec->vlan_priority;
++			ird->vlan_id = rec->vlan_id;
++		}
++		if (ird->ip_type == AF_INET6) {
++			if (!strcmp(rec->ipv6_autocfg, "dhcpv6"))
++				ird->ipv6_autocfg = IPV6_AUTOCFG_DHCPV6;
++			else if (!strcmp(rec->ipv6_autocfg, "nd"))
++				ird->ipv6_autocfg = IPV6_AUTOCFG_ND;
++			else
++				ird->ipv6_autocfg = IPV6_AUTOCFG_NOTSPEC;
++
++			if (!strcmp(rec->linklocal_autocfg, "auto"))
++				ird->linklocal_autocfg = IPV6_LL_AUTOCFG_ON;
++			else if (!strcmp(rec->linklocal_autocfg, "off"))
++				ird->linklocal_autocfg = IPV6_LL_AUTOCFG_OFF;
++			else /* default */
++				ird->linklocal_autocfg = IPV6_LL_AUTOCFG_ON;
++
++			if (!strcmp(rec->router_autocfg, "auto"))
++				ird->router_autocfg = IPV6_RTR_AUTOCFG_ON;
++			else if (!strcmp(rec->router_autocfg, "off"))
++				ird->router_autocfg = IPV6_RTR_AUTOCFG_OFF;
++			else /* default */
++				ird->router_autocfg = IPV6_RTR_AUTOCFG_ON;
++
++			/* Decode the addresses based on the control flags */
++			/* For DHCP, ignore the IPv6 addr in the iface */
++			if (ird->ipv6_autocfg == IPV6_AUTOCFG_DHCPV6)
++				memcpy(&ird->ipv6_addr, all_zeroes_addr6,
++				       sizeof(struct in6_addr));
++			/* Subnet mask priority: CIDR, then rec */
++			if (!ird->ipv6_subnet_mask.s6_addr)
++				inet_pton(AF_INET, rec->subnet_mask,
++					  &ird->ipv6_subnet_mask);
++
++			/* For LL on, ignore the IPv6 addr in the iface */
++			if (ird->linklocal_autocfg == IPV6_LL_AUTOCFG_OFF) {
++				if (strlen(rec->ipv6_linklocal) > NI_MAXHOST)
++					strncpy(ipaddr_str, rec->ipv6_linklocal,
++						NI_MAXHOST);
++				else
++					strcpy(ipaddr_str, rec->ipv6_linklocal);
++				inet_pton(AF_INET6, ipaddr_str,
++					  &ird->ipv6_linklocal);
++			}
++
++			/* For RTR on, ignore the IPv6 addr in the iface */
++			if (ird->router_autocfg == IPV6_RTR_AUTOCFG_OFF) {
++				if (strlen(rec->ipv6_router) > NI_MAXHOST)
++					strncpy(ipaddr_str, rec->ipv6_router,
++						NI_MAXHOST);
++				else
++					strcpy(ipaddr_str, rec->ipv6_router);
++				inet_pton(AF_INET6, ipaddr_str,
++					  &ird->ipv6_router);
++			}
++		} else {
++			/* Subnet mask priority: CIDR, rec, default */
++			if (!ird->ipv4_subnet_mask.s_addr)
++				inet_pton(AF_INET, rec->subnet_mask,
++					  &ird->ipv4_subnet_mask);
++			if (!ird->ipv4_subnet_mask.s_addr)
++				ird->ipv4_subnet_mask.s_addr =
++					calculate_default_netmask(
++							ird->ipv4_addr.s_addr);
++
++			if (strlen(rec->gateway) > NI_MAXHOST)
++				strncpy(ipaddr_str, rec->gateway, NI_MAXHOST);
++			else
++				strcpy(ipaddr_str, rec->gateway);
++			inet_pton(AF_INET, ipaddr_str, &ird->ipv4_gateway);
++		}
++	} else {
++		ird->ipv6_autocfg = IPV6_AUTOCFG_NOTUSED;
++		ird->linklocal_autocfg = IPV6_LL_AUTOCFG_NOTUSED;
++		ird->router_autocfg = IPV6_RTR_AUTOCFG_NOTUSED;
++	}
++	return rc;
++}
++
+ static int parse_iface(void *arg)
+ {
+-	int rc;
++	int rc, i;
+ 	nic_t *nic = NULL;
+-	nic_interface_t *nic_iface, *vlan_iface, *base_nic_iface;
++	nic_interface_t *nic_iface;
+ 	char *transport_name;
+ 	size_t transport_name_size;
+ 	nic_lib_handle_t *handle;
+ 	iscsid_uip_broadcast_t *data;
+-	short int vlan;
+ 	char ipv6_buf_str[INET6_ADDRSTRLEN];
+ 	int request_type = 0;
+-	struct in_addr netmask;
+-	int i, prefix_len = 64;
+-	struct ip_addr_mask ipam;
+ 	struct iface_rec *rec;
+ 	void *res;
++	struct iface_rec_decode ird;
++	struct in_addr src_match, dst_match;
+ 
+ 	data = (iscsid_uip_broadcast_t *) arg;
+ 
+ 	rec = &data->u.iface_rec.rec;
+ 	LOG_INFO(PFX "Received request for '%s' to set IP address: '%s' "
+-		 "VLAN: '%d'", rec->netdev, rec->ipaddress, rec->vlan_id);
+-
+-	vlan = rec->vlan_id;
+-	if (vlan && valid_vlan(vlan) == 0) {
+-		LOG_ERR(PFX "Invalid VLAN tag: %d", rec->vlan_id);
++		 "VLAN: '%d'",
++		 rec->netdev,
++		 rec->ipaddress,
++		 rec->vlan_id);
++
++	rc = decode_iface(&ird, rec);
++	if (ird.vlan_id && valid_vlan(ird.vlan_id) == 0) {
++		LOG_ERR(PFX "Invalid VLAN tag: %d", ird.vlan_id);
+ 		rc = -EIO;
+ 		goto early_exit;
+ 	}
+-
+-	/*  Detect for CIDR notation and strip off the netmask if present */
+-	rc = decode_cidr(rec->ipaddress, &ipam, &prefix_len);
+-	if (rc && !ipam.ip_type) {
+-		LOG_ERR(PFX "decode_cidr: rc=%d, ipam.ip_type=%d",
+-			rc, ipam.ip_type)
+-		    goto early_exit;
+-	}
+-	if (ipam.ip_type == AF_INET6)
+-		inet_ntop(AF_INET6, &ipam.addr6, ipv6_buf_str,
+-			  sizeof(ipv6_buf_str));
++	if (rc && !ird.ip_type) {
++		LOG_ERR(PFX "iface err: rc=%d, ip_type=%d", rc,	ird.ip_type);
++		goto early_exit;
++	}
+ 
+ 	for (i = 0; i < 10; i++) {
+ 		struct timespec sleep_req, sleep_rem;
+@@ -258,11 +369,13 @@ static int parse_iface(void *arg)
+ 	}
+ 
+ 	if (i >= 10) {
+-		LOG_WARN(PFX "Could not aquire nic_list_mutex lock");
++		LOG_WARN(PFX "Could not acquire nic_list_mutex lock");
+ 		rc = -EIO;
+ 		goto early_exit;
+ 	}
+ 
++	/* nic_list_mutex locked */
++
+ 	/*  Check if we can find the NIC device using the netdev
+ 	 *  name */
+ 	rc = from_netdev_name_find_nic(rec->netdev, &nic);
+@@ -298,21 +411,22 @@ static int parse_iface(void *arg)
+ 			 rec->netdev);
+ 	}
+ 
++	pthread_mutex_lock(&nic->nic_mutex);
+ 	if (nic->flags & NIC_GOING_DOWN) {
++		pthread_mutex_unlock(&nic->nic_mutex);
+ 		rc = -EIO;
+ 		LOG_INFO(PFX "nic->flags GOING DOWN");
+ 		goto done;
+ 	}
+ 
+-	/*  If we retry too many times allow iscsid to to timeout */
++	/*  If we retry too many times allow iscsid to timeout */
+ 	if (nic->pending_count > 1000) {
+-		LOG_WARN(PFX "%s: pending count excceded 1000", nic->log_name);
+-
+-		pthread_mutex_lock(&nic->nic_mutex);
+ 		nic->pending_count = 0;
+ 		nic->flags &= ~NIC_ENABLED_PENDING;
+ 		pthread_mutex_unlock(&nic->nic_mutex);
+ 
++		LOG_WARN(PFX "%s: pending count exceeded 1000", nic->log_name);
++
+ 		rc = 0;
+ 		goto done;
+ 	}
+@@ -320,18 +434,19 @@ static int parse_iface(void *arg)
+ 	if (nic->flags & NIC_ENABLED_PENDING) {
+ 		struct timespec sleep_req, sleep_rem;
+ 
++		nic->pending_count++;
++		pthread_mutex_unlock(&nic->nic_mutex);
++
+ 		sleep_req.tv_sec = 0;
+ 		sleep_req.tv_nsec = 100000;
+ 		nanosleep(&sleep_req, &sleep_rem);
+ 
+-		pthread_mutex_lock(&nic->nic_mutex);
+-		nic->pending_count++;
+-		pthread_mutex_unlock(&nic->nic_mutex);
+-
+ 		LOG_INFO(PFX "%s: enabled pending", nic->log_name);
++
+ 		rc = -EAGAIN;
+ 		goto done;
+ 	}
++	pthread_mutex_unlock(&nic->nic_mutex);
+ 
+ 	prepare_library(nic);
+ 
+@@ -359,66 +474,9 @@ static int parse_iface(void *arg)
+ 	LOG_INFO(PFX "%s library set using transport_name %s",
+ 		 nic->log_name, transport_name);
+ 
+-	/*  Create the base network interface if it doesn't exist */
+-	nic_iface = nic_find_nic_iface_protocol(nic, 0, ipam.ip_type);
+-	if (nic_iface == NULL) {
+-		LOG_INFO(PFX "%s couldn't find interface with "
+-			 "ip_type: 0x%x creating it",
+-			 nic->log_name, ipam.ip_type);
+-
+-		/*  Create the nic interface */
+-		nic_iface = nic_iface_init();
+-
+-		if (nic_iface == NULL) {
+-			LOG_ERR(PFX "Couldn't allocate nic_iface", nic_iface);
+-			goto done;
+-		}
+-
+-		nic_iface->protocol = ipam.ip_type;
+-		nic_add_nic_iface(nic, nic_iface);
+-
+-		persist_all_nic_iface(nic);
+-
+-		LOG_INFO(PFX "%s: created network interface", nic->log_name);
+-	} else {
+-		LOG_INFO(PFX "%s: using existing network interface",
+-			 nic->log_name);
+-	}
+-
+-	set_nic_iface(nic, nic_iface);
+-
+-	/* Find the vlan nic_interface */
+-	if (vlan) {
+-		vlan_iface = nic_find_vlan_iface_protocol(nic, nic_iface, vlan,
+-							  ipam.ip_type);
+-		if (vlan_iface == NULL) {
+-			LOG_INFO(PFX "%s couldn't find interface with VLAN = %d"
+-				 "ip_type: 0x%x creating it",
+-				 nic->log_name, vlan, ipam.ip_type);
+-
+-			/*  Create the nic interface */
+-			vlan_iface = nic_iface_init();
+-
+-			if (vlan_iface == NULL) {
+-				LOG_ERR(PFX "Couldn't allocate nic_iface for "
+-					"VLAN: %d", vlan_iface, vlan);
+-				goto done;
+-			}
+-
+-			vlan_iface->protocol = ipam.ip_type;
+-			vlan_iface->vlan_id = vlan;
+-			nic_add_vlan_iface(nic, nic_iface, vlan_iface);
+-		} else {
+-			LOG_INFO(PFX "%s: using existing vlan interface",
+-				 nic->log_name);
+-		}
+-		base_nic_iface = nic_iface;
+-		nic_iface = vlan_iface;
+-	}
+-
+ 	/*  Determine how to configure the IP address */
+-	if (ipam.ip_type == AF_INET) {
+-		if (memcmp(&ipam.addr4,
++	if (ird.ip_type == AF_INET) {
++		if (memcmp(&ird.ipv4_addr,
+ 			   all_zeroes_addr4, sizeof(uip_ip4addr_t)) == 0) {
+ 			LOG_INFO(PFX "%s: requesting configuration using DHCP",
+ 				 nic->log_name);
+@@ -428,51 +486,161 @@ static int parse_iface(void *arg)
+ 				 "static IP address", nic->log_name);
+ 			request_type = IPV4_CONFIG_STATIC;
+ 		}
+-	} else if (ipam.ip_type == AF_INET6) {
+-		if (memcmp(&ipam.addr6,
+-			   all_zeroes_addr6, sizeof(uip_ip6addr_t)) == 0) {
+-			LOG_INFO(PFX
+-				 "%s: requesting configuration using DHCPv6",
+-				 nic->log_name);
++	} else if (ird.ip_type == AF_INET6) {
++		/* For the new 872_22, check ipv6_autocfg for DHCPv6 instead */
++		switch (ird.ipv6_autocfg) {
++		case IPV6_AUTOCFG_DHCPV6:
+ 			request_type = IPV6_CONFIG_DHCP;
+-		} else {
+-			LOG_INFO(PFX "%s: request configuration using static "
+-				 "IPv6 address: '%s'",
+-				 nic->log_name, ipv6_buf_str);
++			break;
++		case IPV6_AUTOCFG_ND:
+ 			request_type = IPV6_CONFIG_STATIC;
++			break;
++		case IPV6_AUTOCFG_NOTSPEC:
++			/* Treat NOTSPEC the same as NOTUSED for now */
++		case IPV6_AUTOCFG_NOTUSED:
++			/* For 871 */
++		default:
++			/* Just the IP address to determine */
++			if (memcmp(&ird.ipv6_addr,
++				   all_zeroes_addr6,
++				   sizeof(struct in6_addr)) == 0)
++				request_type = IPV6_CONFIG_DHCP;
++			else
++				request_type = IPV6_CONFIG_STATIC;
+ 		}
+ 	} else {
+ 		LOG_ERR(PFX "%s: unknown ip_type to configure: 0x%x",
+-			nic->log_name, ipam.ip_type);
++			nic->log_name, ird.ip_type);
+ 
+ 		rc = -EIO;
+ 		goto done;
+ 	}
+ 
++	pthread_mutex_lock(&nic->nic_mutex);
++
++	nic_iface = nic_find_nic_iface(nic, ird.ip_type, ird.vlan_id,
++				       ird.iface_num, request_type);
++
++	if (nic->flags & NIC_PATHREQ_WAIT) {
++		if (!nic_iface ||
++		    !(nic_iface->flags & NIC_IFACE_PATHREQ_WAIT)) {
++			int pathreq_wait;
++
++			if (nic_iface &&
++			    (nic_iface->flags & NIC_IFACE_PATHREQ_WAIT2))
++				pathreq_wait = 12;
++			else
++				pathreq_wait = 10;
++
++			if (nic->pathreq_pending_count < pathreq_wait) {
++				struct timespec sleep_req, sleep_rem;
++
++				pthread_mutex_unlock(&nic->nic_mutex);
++
++				nic->pathreq_pending_count++;
++				sleep_req.tv_sec = 0;
++				sleep_req.tv_nsec = 100000;
++				nanosleep(&sleep_req, &sleep_rem);
++				/* Somebody else is waiting for PATH_REQ */
++				LOG_INFO(PFX "%s: path req pending cnt=%d",
++					 nic->log_name,
++					 nic->pathreq_pending_count);
++				rc = -EAGAIN;
++				goto done;
++			} else {
++				nic->pathreq_pending_count = 0;
++				LOG_DEBUG(PFX "%s: path req pending cnt "
++					  "exceeded!", nic->log_name);
++				/* Allow to fall thru */
++			}
++		}
++	}
++
++	nic->flags |= NIC_PATHREQ_WAIT;
++
++	/* Create the network interface if it doesn't exist */
++	if (nic_iface == NULL) {
++		LOG_DEBUG(PFX "%s couldn't find interface with "
++			  "ip_type: 0x%x creating it",
++			  nic->log_name, ird.ip_type);
++		nic_iface = nic_iface_init();
++
++		if (nic_iface == NULL) {
++			pthread_mutex_unlock(&nic->nic_mutex);
++			LOG_ERR(PFX "%s Couldn't allocate "
++				"interface with ip_type: 0x%x",
++				nic->log_name, ird.ip_type);
++			goto done;
++		}
++		nic_iface->protocol = ird.ip_type;
++		nic_iface->vlan_id = ird.vlan_id;
++		nic_iface->vlan_priority = ird.vlan_priority;
++		if (ird.mtu >= MIN_MTU_SUPPORT && ird.mtu <= MAX_MTU_SUPPORT)
++			nic_iface->mtu = ird.mtu;
++		nic_iface->iface_num = ird.iface_num;
++		nic_iface->request_type = request_type;
++		nic_add_nic_iface(nic, nic_iface);
++
++		persist_all_nic_iface(nic);
++
++		LOG_INFO(PFX "%s: created network interface",
++			 nic->log_name);
++	} else {
++		/* Move the nic_iface to the front */
++		set_nic_iface(nic, nic_iface);
++		LOG_INFO(PFX "%s: using existing network interface",
++			 nic->log_name);
++	}
++
++	nic_iface->flags |= NIC_IFACE_PATHREQ_WAIT1;
++	if (nic->nl_process_thread == INVALID_THREAD) {
++		rc = pthread_create(&nic->nl_process_thread, NULL,
++				    nl_process_handle_thread, nic);
++		if (rc != 0) {
++			LOG_ERR(PFX "%s: Could not create NIC NL "
++				"processing thread [%s]", nic->log_name,
++				strerror(rc));
++			nic->nl_process_thread = INVALID_THREAD;
++			/* Reset both WAIT flags */
++			nic_iface->flags &= ~NIC_IFACE_PATHREQ_WAIT;
++			nic->flags &= ~NIC_PATHREQ_WAIT;
++		}
++	}
++
++	pthread_mutex_unlock(&nic->nic_mutex);
++
+ 	if (nic_iface->ustack.ip_config == request_type) {
++		/* Same request_type, check for STATIC address change */
+ 		if (request_type == IPV4_CONFIG_STATIC) {
+-			if (memcmp(nic_iface->ustack.hostaddr, &ipam.addr4,
++			if (memcmp(nic_iface->ustack.hostaddr, &ird.ipv4_addr,
+ 				   sizeof(struct in_addr)))
+-				goto diff;
++				goto reacquire;
+ 		} else if (request_type == IPV6_CONFIG_STATIC) {
+-			if (memcmp(nic_iface->ustack.hostaddr6, &ipam.addr6,
++			if (memcmp(nic_iface->ustack.hostaddr6, &ird.ipv6_addr,
+ 				   sizeof(struct in6_addr)))
+-				goto diff;
++				goto reacquire;
++			else
++				inet_ntop(AF_INET6, &ird.ipv6_addr,
++					  ipv6_buf_str,
++					  sizeof(ipv6_buf_str));
+ 		}
+ 		LOG_INFO(PFX "%s: IP configuration didn't change using 0x%x",
+ 			 nic->log_name, nic_iface->ustack.ip_config);
+-		goto enable_nic;
+-diff:
+-		/* Disable the NIC */
+-		nic_disable(nic, 0);
+-	} else {
+-		if (request_type == IPV4_CONFIG_DHCP
+-		    || request_type == IPV6_CONFIG_DHCP)
+-			nic->flags |= NIC_RESET_UIP;
++		/* No need to acquire the IP address */
++		inet_ntop(AF_INET6, &ird.ipv6_addr, ipv6_buf_str,
++			  sizeof(ipv6_buf_str));
+ 
+-		/* Disable the NIC */
+-		nic_disable(nic, 0);
++		goto enable_nic;
+ 	}
++reacquire:
++	/* Config needs to re-acquire for this nic_iface */
++	pthread_mutex_lock(&nic->nic_mutex);
++	nic_iface->flags |= NIC_IFACE_ACQUIRE;
++	pthread_mutex_unlock(&nic->nic_mutex);
++
++	/* Disable the nic loop from further processing, upon returned,
++	   the nic_iface should be cleared */
++	nic_disable(nic, 0);
+ 
+ 	/*  Check to see if this is using DHCP or if this is
+ 	 *  a static IPv4 address.  This is done by checking
+@@ -485,97 +653,96 @@ diff:
+ 		memset(nic_iface->ustack.hostaddr, 0, sizeof(struct in_addr));
+ 		LOG_INFO(PFX "%s: configuring using DHCP", nic->log_name);
+ 		nic_iface->ustack.ip_config = IPV4_CONFIG_DHCP;
+-
+ 		break;
++
+ 	case IPV4_CONFIG_STATIC:
+-		memcpy(nic_iface->ustack.hostaddr, &ipam.addr4,
++		memcpy(nic_iface->ustack.hostaddr, &ird.ipv4_addr,
+ 		       sizeof(struct in_addr));
+ 		LOG_INFO(PFX "%s: configuring using static IP "
+ 			 "IPv4 address :%s ",
+-			 nic->log_name, inet_ntoa(ipam.addr4));
+-		netmask.s_addr = ipam.nm4.s_addr;
+-		if (!netmask.s_addr)
+-			netmask.s_addr =
+-			    calculate_default_netmask(ipam.addr4.s_addr);
+-		memcpy(nic_iface->ustack.netmask,
+-		       &netmask, sizeof(netmask.s_addr));
+-		LOG_INFO(PFX "  netmask :%s", inet_ntoa(netmask));
+-
++			 nic->log_name, inet_ntoa(ird.ipv4_addr));
++
++		if (ird.ipv4_subnet_mask.s_addr)
++			memcpy(nic_iface->ustack.netmask,
++			       &ird.ipv4_subnet_mask, sizeof(struct in_addr));
++		LOG_INFO(PFX " netmask: %s", inet_ntoa(ird.ipv4_subnet_mask));
++
++		/* Default route */
++		if (ird.ipv4_gateway.s_addr) {
++			/* Check for validity */
++			src_match.s_addr = ird.ipv4_addr.s_addr &
++					   ird.ipv4_subnet_mask.s_addr;
++			dst_match.s_addr = ird.ipv4_gateway.s_addr &
++					   ird.ipv4_subnet_mask.s_addr;
++			if (src_match.s_addr == dst_match.s_addr)
++				memcpy(nic_iface->ustack.default_route_addr,
++				       &ird.ipv4_gateway,
++				       sizeof(struct in_addr));
++		}
+ 		nic_iface->ustack.ip_config = IPV4_CONFIG_STATIC;
+ 		break;
++
+ 	case IPV6_CONFIG_DHCP:
+ 		memset(nic_iface->ustack.hostaddr6, 0,
+ 		       sizeof(struct in6_addr));
+-		nic_iface->ustack.prefix_len = prefix_len;
+-		if (ipam.nm6.s6_addr[0] | ipam.nm6.s6_addr[1] |
+-		    ipam.nm6.s6_addr[2] | ipam.nm6.s6_addr[3] |
+-		    ipam.nm6.s6_addr[4] | ipam.nm6.s6_addr[5] |
+-		    ipam.nm6.s6_addr[6] | ipam.nm6.s6_addr[7])
++		nic_iface->ustack.prefix_len = ird.prefix_len;
++		nic_iface->ustack.ipv6_autocfg = ird.ipv6_autocfg;
++		nic_iface->ustack.linklocal_autocfg = ird.linklocal_autocfg;
++		nic_iface->ustack.router_autocfg = ird.router_autocfg;
++
++		if (memcmp(&ird.ipv6_subnet_mask, all_zeroes_addr6,
++			   sizeof(struct in6_addr)))
+ 			memcpy(nic_iface->ustack.netmask6,
+-			       &ipam.nm6, sizeof(struct in6_addr));
++			       &ird.ipv6_subnet_mask, sizeof(struct in6_addr));
++		if (ird.linklocal_autocfg == IPV6_LL_AUTOCFG_OFF)
++			memcpy(nic_iface->ustack.linklocal6,
++			       &ird.ipv6_linklocal, sizeof(struct in6_addr));
++		if (ird.router_autocfg == IPV6_RTR_AUTOCFG_OFF)
++			memcpy(nic_iface->ustack.default_route_addr6,
++			       &ird.ipv6_router, sizeof(struct in6_addr));
++		inet_ntop(AF_INET6, &ird.ipv6_addr, ipv6_buf_str,
++			  sizeof(ipv6_buf_str));
+ 		LOG_INFO(PFX "%s: configuring using DHCPv6",
+ 			 nic->log_name);
+ 		nic_iface->ustack.ip_config = IPV6_CONFIG_DHCP;
+ 		break;
++
+ 	case IPV6_CONFIG_STATIC:
+-		memcpy(nic_iface->ustack.hostaddr6, &ipam.addr6,
++		memcpy(nic_iface->ustack.hostaddr6, &ird.ipv6_addr,
+ 		       sizeof(struct in6_addr));
++		nic_iface->ustack.prefix_len = ird.prefix_len;
++		nic_iface->ustack.ipv6_autocfg = ird.ipv6_autocfg;
++		nic_iface->ustack.linklocal_autocfg = ird.linklocal_autocfg;
++		nic_iface->ustack.router_autocfg = ird.router_autocfg;
+ 
+-		nic_iface->ustack.prefix_len = prefix_len;
+-		if (ipam.nm6.s6_addr[0] | ipam.nm6.s6_addr[1] |
+-		    ipam.nm6.s6_addr[2] | ipam.nm6.s6_addr[3] |
+-		    ipam.nm6.s6_addr[4] | ipam.nm6.s6_addr[5] |
+-		    ipam.nm6.s6_addr[6] | ipam.nm6.s6_addr[7])
++		if (memcmp(&ird.ipv6_subnet_mask, all_zeroes_addr6,
++			   sizeof(struct in6_addr)))
+ 			memcpy(nic_iface->ustack.netmask6,
+-			       &ipam.nm6, sizeof(struct in6_addr));
+-
++			       &ird.ipv6_subnet_mask, sizeof(struct in6_addr));
++		if (ird.linklocal_autocfg == IPV6_LL_AUTOCFG_OFF)
++			memcpy(nic_iface->ustack.linklocal6,
++			       &ird.ipv6_linklocal, sizeof(struct in6_addr));
++		if (ird.router_autocfg == IPV6_RTR_AUTOCFG_OFF)
++			memcpy(nic_iface->ustack.default_route_addr6,
++			       &ird.ipv6_router, sizeof(struct in6_addr));
++
++		inet_ntop(AF_INET6, &ird.ipv6_addr, ipv6_buf_str,
++			  sizeof(ipv6_buf_str));
+ 		LOG_INFO(PFX "%s: configuring using static IP "
+ 			 "IPv6 address: '%s'", nic->log_name, ipv6_buf_str);
+ 
+ 		nic_iface->ustack.ip_config = IPV6_CONFIG_STATIC;
+ 		break;
++
+ 	default:
+ 		LOG_INFO(PFX "%s: Unknown request type: 0x%x",
+ 			 nic->log_name, request_type);
+ 
+ 	}
+ 
+-	/* Configuration changed, do VLAN WA */
+-	vlan_iface = nic_iface->vlan_next;
+-	while (vlan_iface) {
+-		/* TODO: When VLAN support is placed in the iface file
+-		* revisit this code */
+-		if (vlan_iface->ustack.ip_config) {
+-			vlan_iface->ustack.ip_config =
+-				nic_iface->ustack.ip_config;
+-			memcpy(vlan_iface->ustack.hostaddr,
+-			       nic_iface->ustack.hostaddr,
+-			       sizeof(nic_iface->ustack.hostaddr));
+-			memcpy(vlan_iface->ustack.netmask,
+-			       nic_iface->ustack.netmask,
+-			       sizeof(nic_iface->ustack.netmask));
+-			memcpy(vlan_iface->ustack.hostaddr6,
+-			       nic_iface->ustack.hostaddr6,
+-			       sizeof(nic_iface->ustack.hostaddr6));
+-			memcpy(vlan_iface->ustack.netmask6,
+-			       nic_iface->ustack.netmask6,
+-			       sizeof(nic_iface->ustack.netmask6));
+-		}
+-		vlan_iface = vlan_iface->vlan_next;
+-	}
+-
+ enable_nic:
+-	if (nic->state & NIC_STOPPED) {
+-		pthread_mutex_lock(&nic->nic_mutex);
+-		if (nic->flags & NIC_ENABLED_PENDING) {
+-			/* Still waiting */
+-			pthread_mutex_unlock(&nic->nic_mutex);
+-			rc = 0;
+-			goto enable_out;
+-		}
+-		nic->flags |= NIC_ENABLED_PENDING;
+-		pthread_mutex_unlock(&nic->nic_mutex);
+-
++	switch (nic->state) {
++	case NIC_STOPPED:
+ 		/* This thread will be thrown away when completed */
+ 		if (nic->enable_thread != INVALID_THREAD) {
+ 			rc = pthread_join(nic->enable_thread, &res);
+@@ -592,19 +759,27 @@ enable_nic:
+ 				 nic->log_name);
+ eagain:
+ 		rc = -EAGAIN;
+-	} else {
++		break;
++
++	case NIC_RUNNING:
+ 		LOG_INFO(PFX "%s: NIC already enabled "
+ 			 "flags: 0x%x state: 0x%x\n",
+ 			 nic->log_name, nic->flags, nic->state);
+ 		rc = 0;
++		break;
++	default:
++		LOG_INFO(PFX "%s: NIC enable still in progress "
++			 "flags: 0x%x state: 0x%x\n",
++			 nic->log_name, nic->flags, nic->state);
++		rc = -EAGAIN;
+ 	}
+-enable_out:
++
+ 	LOG_INFO(PFX "ISCSID_UIP_IPC_GET_IFACE: command: %x "
+ 		 "name: %s, netdev: %s ipaddr: %s vlan: %d transport_name:%s",
+ 		 data->header.command, rec->name, rec->netdev,
+-		 (ipam.ip_type == AF_INET) ? inet_ntoa(ipam.addr4) :
++		 (ird.ip_type == AF_INET) ? inet_ntoa(ird.ipv4_addr) :
+ 					     ipv6_buf_str,
+-		 vlan, rec->transport_name);
++		 ird.vlan_id, rec->transport_name);
+ 
+ done:
+ 	pthread_mutex_unlock(&nic_list_mutex);
+@@ -638,12 +813,13 @@ int process_iscsid_broadcast(int s2)
+ 	data = (iscsid_uip_broadcast_t *) calloc(1, sizeof(*data));
+ 	if (data == NULL) {
+ 		LOG_ERR(PFX "Couldn't allocate memory for iface data");
+-		return -ENOMEM;
++		rc = -ENOMEM;
++		goto error;
+ 	}
+ 	memset(data, 0, sizeof(*data));
+ 
+ 	size = fread(data, sizeof(iscsid_uip_broadcast_header_t), 1, fd);
+-	if (size == -1) {
++	if (!size) {
+ 		LOG_ERR(PFX "Could not read request: %d(%s)",
+ 			errno, strerror(errno));
+ 		rc = ferror(fd);
+@@ -657,7 +833,7 @@ int process_iscsid_broadcast(int s2)
+ 		  cmd, payload_len);
+ 
+ 	size = fread(&data->u.iface_rec, payload_len, 1, fd);
+-	if (size == -1) {
++	if (!size) {
+ 		LOG_ERR(PFX "Could not read data: %d(%s)",
+ 			errno, strerror(errno));
+ 		goto error;
+diff --git a/src/unix/libs/bnx2.c b/src/unix/libs/bnx2.c
+index 112d570..a8300c2 100644
+--- a/src/unix/libs/bnx2.c
++++ b/src/unix/libs/bnx2.c
+@@ -295,7 +295,7 @@ static int bnx2_uio_verify(nic_t * nic)
+ 
+ 	LOG_INFO(PFX "%s: Verified is a cnic_uio device", nic->log_name);
+ 
+-      error:
++error:
+ 	return rc;
+ }
+ 
+@@ -395,7 +395,7 @@ static void bnx2_free(nic_t *nic)
+ /**
+  *  bnx2_alloc() - Used to allocate a bnx2 structure
+  */
+-static bnx2_t *bnx2_alloc(nic_t * nic)
++static bnx2_t *bnx2_alloc(nic_t *nic)
+ {
+ 	bnx2_t *bp = malloc(sizeof(*bp));
+ 	if (bp == NULL) {
+@@ -468,12 +468,14 @@ static int bnx2_open(nic_t * nic)
+ 			manually_trigger_uio_event(nic, nic->uio_minor);
+ 
+ 			/*  udev might not have created the file yet */
++			pthread_mutex_unlock(&nic->nic_mutex);
+ 			sleep(1);
++			pthread_mutex_lock(&nic->nic_mutex);
+ 		}
+ 	}
+ 	if (fstat(nic->fd, &uio_stat) < 0) {
+ 		LOG_ERR(PFX "%s: Could not fstat device", nic->log_name);
+-		rc = -ENODEV;
++		errno = -ENODEV;
+ 		goto error_alloc_rx_ring;
+ 	}
+ 	nic->uio_minor = minor(uio_stat.st_rdev);
+@@ -483,7 +485,7 @@ static int bnx2_open(nic_t * nic)
+ 	if (bp->bar0_fd < 0) {
+ 		LOG_ERR(PFX "%s: Could not open %s", nic->log_name,
+ 			sysfs_resc_path);
+-		rc = -ENODEV;
++		errno = -ENODEV;
+ 		goto error_alloc_rx_ring;
+ 	}
+ 
+@@ -506,6 +508,7 @@ static int bnx2_open(nic_t * nic)
+ 	if (bp->rx_ring == NULL) {
+ 		LOG_ERR(PFX "%s: Could not allocate space for rx_ring",
+ 			nic->log_name);
++		errno = -ENOMEM;
+ 		goto error_alloc_rx_ring;
+ 	}
+ 	mlock(bp->rx_ring, sizeof(struct l2_fhdr *) * bp->rx_ring_size);
+@@ -515,6 +518,7 @@ static int bnx2_open(nic_t * nic)
+ 	if (bp->rx_pkt_ring == NULL) {
+ 		LOG_ERR(PFX "%s: Could not allocate space for rx_pkt_ring",
+ 			nic->log_name);
++		errno = -ENOMEM;
+ 		goto error_alloc_rx_pkt_ring;
+ 	}
+ 	mlock(bp->rx_pkt_ring, sizeof(void *) * bp->rx_ring_size);
+@@ -677,9 +681,10 @@ static int bnx2_open(nic_t * nic)
+ 	bnx2_wr32(bp, BNX2_RPM_SORT_USER2, val | BNX2_RPM_SORT_USER2_ENA);
+ 
+ 	rc = enable_multicast(nic);
+-	if (rc != 0)
++	if (rc != 0) {
++		errno = rc;
+ 		goto error_bufs;
+-
++	}
+ 	msync(bp->reg, 0x12800, MS_SYNC);
+ 	LOG_INFO("%s: bnx2 uio initialized", nic->log_name);
+ 
+@@ -707,6 +712,10 @@ error_alloc_rx_pkt_ring:
+ 	bp->rx_ring = NULL;
+ 
+ error_alloc_rx_ring:
++	if (nic->fd != INVALID_FD) {
++		close(nic->fd);
++		nic->fd = INVALID_FD;
++	}
+ 	bnx2_free(nic);
+ 
+ 	return errno;
+@@ -878,8 +887,8 @@ void bnx2_start_xmit(nic_t * nic, size_t len, u16_t vlan_id)
+ 	rxbd = (struct rx_bd *)(((__u8 *) bp->tx_ring) + getpagesize());
+ 
+ 	if ((rxbd->rx_bd_haddr_hi == 0) && (rxbd->rx_bd_haddr_lo == 0)) {
+-		LOG_DEBUG(PFX "%s: trying to transmit when device is closed",
+-			  nic->log_name);
++		LOG_PACKET(PFX "%s: trying to transmit when device is closed",
++			   nic->log_name);
+ 		pthread_mutex_unlock(&nic->xmit_mutex);
+ 		return;
+ 	}
+@@ -905,8 +914,8 @@ void bnx2_start_xmit(nic_t * nic, size_t len, u16_t vlan_id)
+ 	bnx2_reg_sync(bp, bp->tx_bidx_io, sizeof(__u16));
+ 	bnx2_reg_sync(bp, bp->tx_bseq_io, sizeof(__u32));
+ 
+-	LOG_DEBUG(PFX "%s: sent %d bytes using dev->tx_prod: %d",
+-		  nic->log_name, len, bp->tx_prod);
++	LOG_PACKET(PFX "%s: sent %d bytes using dev->tx_prod: %d",
++		   nic->log_name, len, bp->tx_prod);
+ }
+ 
+ /**
+@@ -917,8 +926,8 @@ void bnx2_start_xmit(nic_t * nic, size_t len, u16_t vlan_id)
+  */
+ int bnx2_write(nic_t * nic, nic_interface_t * nic_iface, packet_t * pkt)
+ {
+-	bnx2_t *bp = (bnx2_t *) nic->priv;
+-	struct uip_stack *uip = &nic_iface->ustack;
++	bnx2_t *bp;
++	struct uip_stack *uip;
+ 
+ 	/* Sanity Check: validate the parameters */
+ 	if (nic == NULL || nic_iface == NULL || pkt == NULL) {
+@@ -927,6 +936,8 @@ int bnx2_write(nic_t * nic, nic_interface_t * nic_iface, packet_t * pkt)
+ 			" pkt == 0x%x", nic, nic_iface, pkt);
+ 		return -EINVAL;
+ 	}
++	bp = (bnx2_t *)nic->priv;
++	uip = &nic_iface->ustack;
+ 
+ 	if (pkt->buf_size == 0) {
+ 		LOG_ERR(PFX "%s: Trying to transmitted 0 sized packet",
+@@ -935,22 +946,24 @@ int bnx2_write(nic_t * nic, nic_interface_t * nic_iface, packet_t * pkt)
+ 	}
+ 
+ 	if (pthread_mutex_trylock(&nic->xmit_mutex) != 0) {
+-		LOG_DEBUG(PFX "%s: Dropped previous transmitted packet",
+-			  nic->log_name);
++		LOG_PACKET(PFX "%s: Dropped previous transmitted packet",
++			   nic->log_name);
+ 		return -EINVAL;
+ 	}
+ 
+ 	bnx2_prepare_xmit_packet(nic, nic_iface, pkt);
+-	bnx2_start_xmit(nic, pkt->buf_size, nic_iface->vlan_id);
++	bnx2_start_xmit(nic, pkt->buf_size,
++			(nic_iface->vlan_priority << 12) |
++			nic_iface->vlan_id);
+ 
+ 	/*  bump the bnx2 dev send statistics */
+ 	nic->stats.tx.packets++;
+ 	nic->stats.tx.bytes += uip->uip_len;
+ 
+-	LOG_DEBUG(PFX "%s: transmitted %d bytes "
+-		  "dev->tx_cons: %d, dev->tx_prod: %d, dev->tx_bseq:%d",
+-		  nic->log_name, pkt->buf_size,
+-		  bp->tx_cons, bp->tx_prod, bp->tx_bseq);
++	LOG_PACKET(PFX "%s: transmitted %d bytes "
++		   "dev->tx_cons: %d, dev->tx_prod: %d, dev->tx_bseq:%d",
++		   nic->log_name, pkt->buf_size,
++		   bp->tx_cons, bp->tx_prod, bp->tx_bseq);
+ 
+ 	return 0;
+ }
+@@ -963,7 +976,7 @@ int bnx2_write(nic_t * nic, nic_interface_t * nic_iface, packet_t * pkt)
+  */
+ static int bnx2_read(nic_t * nic, packet_t * pkt)
+ {
+-	bnx2_t *bp = (bnx2_t *) nic->priv;
++	bnx2_t *bp;
+ 	int rc = 0;
+ 	uint16_t hw_cons, sw_cons;
+ 
+@@ -973,6 +986,7 @@ static int bnx2_read(nic_t * nic, packet_t * pkt)
+ 			" pkt == 0x%x", nic, pkt);
+ 		return -EINVAL;
+ 	}
++	bp = (bnx2_t *)nic->priv;
+ 
+ 	hw_cons = bp->get_rx_cons(bp);
+ 	sw_cons = bp->rx_cons;
+@@ -984,8 +998,8 @@ static int bnx2_read(nic_t * nic, packet_t * pkt)
+ 		int len;
+ 		uint16_t errors;
+ 
+-		LOG_DEBUG(PFX "%s: clearing rx interrupt: %d %d %d",
+-			  nic->log_name, sw_cons, hw_cons, rx_index);
++		LOG_PACKET(PFX "%s: clearing rx interrupt: %d %d %d",
++			   nic->log_name, sw_cons, hw_cons, rx_index);
+ 
+ 		msync(rx_hdr, sizeof(struct l2_fhdr), MS_SYNC);
+ 		errors = ((rx_hdr->l2_fhdr_status & 0xffff0000) >> 16);
+@@ -1033,8 +1047,8 @@ static int bnx2_read(nic_t * nic, packet_t * pkt)
+ 
+ 				rc = 1;
+ 
+-				LOG_DEBUG(PFX "%s: processing packet "
+-					  "length: %d", nic->log_name, len);
++				LOG_PACKET(PFX "%s: processing packet "
++					   "length: %d", nic->log_name, len);
+ 			} else {
+ 				/*  If the NIC passes up a packet bigger
+ 				 *  then the RX buffer, flag it */
+@@ -1073,21 +1087,23 @@ static int bnx2_read(nic_t * nic, packet_t * pkt)
+  */
+ static int bnx2_clear_tx_intr(nic_t * nic)
+ {
+-	bnx2_t *bp = (bnx2_t *) nic->priv;
+-	uint16_t hw_cons = bp->get_tx_cons(bp);
++	bnx2_t *bp;
++	uint16_t hw_cons;
+ 
+ 	/* Sanity check: ensure the parameters passed in are valid */
+ 	if (unlikely(nic == NULL)) {
+ 		LOG_ERR(PFX "bnx2_read() nic == NULL");
+ 		return -EINVAL;
+ 	}
++	bp = (bnx2_t *) nic->priv;
++	hw_cons = bp->get_tx_cons(bp);
+ 
+ 	if (bp->flags & BNX2_UIO_TX_HAS_SENT) {
+ 		bp->flags &= ~BNX2_UIO_TX_HAS_SENT;
+ 	}
+ 
+-	LOG_DEBUG(PFX "%s: clearing tx interrupt [%d %d]",
+-		  nic->log_name, bp->tx_cons, hw_cons);
++	LOG_PACKET(PFX "%s: clearing tx interrupt [%d %d]",
++		   nic->log_name, bp->tx_cons, hw_cons);
+ 
+ 	bp->tx_cons = hw_cons;
+ 
+@@ -1097,7 +1113,7 @@ static int bnx2_clear_tx_intr(nic_t * nic)
+ 	if (nic->tx_packet_queue != NULL) {
+ 		packet_t *pkt;
+ 
+-		LOG_DEBUG(PFX "%s: sending queued tx packet", nic->log_name);
++		LOG_PACKET(PFX "%s: sending queued tx packet", nic->log_name);
+ 		pkt = nic_dequeue_tx_packet(nic);
+ 
+ 		/*  Got a TX packet buffer of the TX queue and put it onto
+@@ -1106,13 +1122,14 @@ static int bnx2_clear_tx_intr(nic_t * nic)
+ 			bnx2_prepare_xmit_packet(nic, pkt->nic_iface, pkt);
+ 
+ 			bnx2_start_xmit(nic, pkt->buf_size,
++					(pkt->nic_iface->vlan_priority << 12) |
+ 					pkt->nic_iface->vlan_id);
+ 
+-			LOG_DEBUG(PFX "%s: transmitted queued packet %d bytes "
+-				  "dev->tx_cons: %d, dev->tx_prod: %d, "
+-				  "dev->tx_bseq:%d",
+-				  nic->log_name, pkt->buf_size,
+-				  bp->tx_cons, bp->tx_prod, bp->tx_bseq);
++			LOG_PACKET(PFX "%s: transmitted queued packet %d bytes "
++				   "dev->tx_cons: %d, dev->tx_prod: %d, "
++				   "dev->tx_bseq:%d",
++				   nic->log_name, pkt->buf_size,
++				   bp->tx_cons, bp->tx_prod, bp->tx_bseq);
+ 
+ 			return -EAGAIN;
+ 		}
+diff --git a/src/unix/libs/bnx2x.c b/src/unix/libs/bnx2x.c
+index fa32fbc..5e33420 100644
+--- a/src/unix/libs/bnx2x.c
++++ b/src/unix/libs/bnx2x.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2009-2011, Broadcom Corporation
++ * Copyright (c) 2009-2012, Broadcom Corporation
+  *
+  * Written by:  Benjamin Li  (benli at broadcom.com)
+  * 
+@@ -288,11 +288,12 @@ static void bnx2x_set_drv_version_unknown(bnx2x_t * bp)
+ 	bp->version.sub_minor = BNX2X_UNKNOWN_SUB_MINOR_VERSION;
+ }
+ 
++/* Return: 1 = Unknown, 0 = Known */
+ static int bnx2x_is_drv_version_unknown(struct bnx2x_driver_version *version)
+ {
+-	if ((version->major == BNX2X_UNKNOWN_MAJOR_VERSION) &&
+-	    (version->minor == BNX2X_UNKNOWN_MINOR_VERSION) &&
+-	    (version->sub_minor == BNX2X_UNKNOWN_SUB_MINOR_VERSION)) {
++	if ((version->major == (uint16_t)BNX2X_UNKNOWN_MAJOR_VERSION) &&
++	    (version->minor == (uint16_t)BNX2X_UNKNOWN_MINOR_VERSION) &&
++	    (version->sub_minor == (uint16_t)BNX2X_UNKNOWN_SUB_MINOR_VERSION)) {
+ 		return 1;
+ 	}
+ 
+@@ -595,7 +596,7 @@ static void bnx2x_free(nic_t *nic)
+ /**
+  *  bnx2x_alloc() - Used to allocate a bnx2x structure
+  */
+-static bnx2x_t *bnx2x_alloc(nic_t * nic)
++static bnx2x_t *bnx2x_alloc(nic_t *nic)
+ {
+ 	bnx2x_t *bp = malloc(sizeof(*bp));
+ 
+@@ -652,9 +653,13 @@ static int bnx2x_open(nic_t * nic)
+ 	if (bp == NULL)
+ 		return -ENOMEM;
+ 
+-	if (!bnx2x_is_drv_version_unknown(&bnx2x_version))
+-		bnx2x_get_drv_version(bp);
+-	else {
++	if (bnx2x_is_drv_version_unknown(&bnx2x_version)) {
++		/* If version is unknown, go read from ethtool */
++		rc = bnx2x_get_drv_version(bp);
++		if (rc)
++			goto open_error;
++	} else {
++		/* Version is not unknown, jsut use it */
+ 		bnx2x_version.major = bp->version.major;
+ 		bnx2x_version.minor = bp->version.minor;
+ 		bnx2x_version.sub_minor = bp->version.sub_minor;
+@@ -663,7 +668,9 @@ static int bnx2x_open(nic_t * nic)
+ 	count = 0;
+ 	while ((nic->fd < 0) && count < 15) {
+ 		/*  udev might not have created the file yet */
++		pthread_mutex_unlock(&nic->nic_mutex);
+ 		sleep(1);
++		pthread_mutex_lock(&nic->nic_mutex);
+ 
+ 		nic->fd = open(nic->uio_device_name, O_RDWR | O_NONBLOCK);
+ 		if (nic->fd != INVALID_FD) {
+@@ -684,7 +691,9 @@ static int bnx2x_open(nic_t * nic)
+ 			manually_trigger_uio_event(nic, nic->uio_minor);
+ 
+ 			/*  udev might not have created the file yet */
++			pthread_mutex_unlock(&nic->nic_mutex);
+ 			sleep(1);
++			pthread_mutex_lock(&nic->nic_mutex);
+ 
+ 			count++;
+ 		}
+@@ -820,7 +829,15 @@ static int bnx2x_open(nic_t * nic)
+ 			 nic->log_name);
+ 		goto open_error;
+ 	}
+-
++	/* In E1/E1H use pci device function as read from sysfs.
++	 * In E2/E3 read physical function from ME register since these chips
++	 * support Physical Device Assignment where kernel BDF maybe arbitrary
++	 * (depending on hypervisor).
++	 */
++	if (CHIP_IS_E2_PLUS(bp)) {
++		func = (bnx2x_rd32(bp, BAR_ME_REGISTER) & ME_REG_ABS_PF_NUM) >>
++			ME_REG_ABS_PF_NUM_SHIFT;
++	}
+ 	bp->func = func;
+ 	bp->port = bp->func % PORT_MAX;
+ 
+@@ -976,9 +993,12 @@ static int bnx2x_open(nic_t * nic)
+ 			val = bnx2x_rd32(bp, mf_cfg_addr + ovtag_offset);
+ 			val &= 0xffff;
+ 			/* SD mode, check for valid outer VLAN */
+-			if (val == 0xffff)
+-				goto open_error;
+-
++			if (val == 0xffff) {
++				LOG_ERR(PFX "%s: Invalid OV detected for SD, "
++					" fallback to SF mode!\n",
++					nic->log_name);
++				goto SF;
++			}
+ 			/* Check for iSCSI protocol */
+ 			val = bnx2x_rd32(bp, mf_cfg_addr + proto_offset);
+ 			if ((val & 6) != 6)
+@@ -995,10 +1015,9 @@ static int bnx2x_open(nic_t * nic)
+ 			mac[4] = (__u8) (val >> 8);
+ 			mac[5] = (__u8) val;
+ 			memcpy(nic->mac_addr, mac, 6);
+-
+ 		}
+ 	}
+-
++SF:
+ 	LOG_INFO(PFX "%s:  Using mac address: %02x:%02x:%02x:%02x:%02x:%02x",
+ 		 nic->log_name,
+ 		 nic->mac_addr[0], nic->mac_addr[1], nic->mac_addr[2],
+@@ -1053,6 +1072,10 @@ open_error:
+ 		close(bp->bar0_fd);
+ 		bp->bar0_fd = INVALID_FD;
+ 	}
++	if (nic->fd != INVALID_FD) {
++		close(nic->fd);
++		nic->fd = INVALID_FD;
++	}
+ 	bnx2x_free(nic);
+ 
+ 	return rc;
+@@ -1165,9 +1188,12 @@ static int bnx2x_uio_close_resources(nic_t * nic, NIC_SHUTDOWN_T graceful)
+ static int bnx2x_close(nic_t * nic, NIC_SHUTDOWN_T graceful)
+ {
+ 	/*  Sanity Check: validate the parameters */
+-	if (nic == NULL || nic->priv == NULL) {
+-		LOG_ERR(PFX "bnx2x_close(): nic == %p, bp == %p", nic,
+-			nic->priv);
++	if (nic == NULL) {
++		LOG_ERR(PFX "bnx2x_close(): nic == NULL");
++		return -EINVAL;
++	}
++	if (nic->priv == NULL) {
++		LOG_ERR(PFX "bnx2x_close(): nic->priv == NULL");
+ 		return -EINVAL;
+ 	}
+ 
+@@ -1227,8 +1253,8 @@ void bnx2x_start_xmit(nic_t * nic, size_t len, u16_t vlan_id)
+ 	rx_bd = (struct eth_rx_bd *)(((__u8 *) bp->tx_ring) + getpagesize());
+ 
+ 	if ((rx_bd->addr_hi == 0) && (rx_bd->addr_lo == 0)) {
+-		LOG_DEBUG(PFX "%s: trying to transmit when device is closed",
+-			  nic->log_name);
++		LOG_PACKET(PFX "%s: trying to transmit when device is closed",
++			   nic->log_name);
+ 		pthread_mutex_unlock(&nic->xmit_mutex);
+ 		return;
+ 	}
+@@ -1251,7 +1277,7 @@ void bnx2x_start_xmit(nic_t * nic, size_t len, u16_t vlan_id)
+ 	bp->tx_bd_prod = BNX2X_NEXT_TX_BD(bp->tx_bd_prod);
+ 
+ 	barrier();
+-	if (nl_process_if_down == 0) {
++	if (nic->nl_process_if_down == 0) {
+ 		bnx2x_doorbell(bp, bp->tx_doorbell, 0x02 |
+ 			       (bp->tx_bd_prod << 16));
+ 		bnx2x_flush_doorbell(bp, bp->tx_doorbell);
+@@ -1262,8 +1288,8 @@ void bnx2x_start_xmit(nic_t * nic, size_t len, u16_t vlan_id)
+ 		 */
+ 		pthread_mutex_unlock(&nic->xmit_mutex);
+ 	}
+-	LOG_DEBUG(PFX "%s: sent %d bytes using bp->tx_prod: %d",
+-		  nic->log_name, len, bp->tx_prod);
++	LOG_PACKET(PFX "%s: sent %d bytes using bp->tx_prod: %d",
++		   nic->log_name, len, bp->tx_prod);
+ }
+ 
+ /**
+@@ -1274,8 +1300,8 @@ void bnx2x_start_xmit(nic_t * nic, size_t len, u16_t vlan_id)
+  */
+ int bnx2x_write(nic_t * nic, nic_interface_t * nic_iface, packet_t * pkt)
+ {
+-	bnx2x_t *bp = (bnx2x_t *) nic->priv;
+-	struct uip_stack *uip = &nic_iface->ustack;
++	bnx2x_t *bp;
++	struct uip_stack *uip;
+ 	int i = 0;
+ 
+ 	/* Sanity Check: validate the parameters */
+@@ -1285,6 +1311,8 @@ int bnx2x_write(nic_t * nic, nic_interface_t * nic_iface, packet_t * pkt)
+ 			" pkt == 0x%x", nic, nic_iface, pkt);
+ 		return -EINVAL;
+ 	}
++	bp = (bnx2x_t *) nic->priv;
++	uip = &nic_iface->ustack;
+ 
+ 	if (pkt->buf_size == 0) {
+ 		LOG_ERR(PFX "%s: Trying to transmitted 0 sized packet",
+@@ -1304,22 +1332,24 @@ int bnx2x_write(nic_t * nic, nic_interface_t * nic_iface, packet_t * pkt)
+ 	}
+ 
+ 	if (pthread_mutex_trylock(&nic->xmit_mutex) != 0) {
+-		LOG_DEBUG(PFX "%s: Dropped previous transmitted packet",
+-			  nic->log_name);
++		LOG_PACKET(PFX "%s: Dropped previous transmitted packet",
++			   nic->log_name);
+ 		return -EINVAL;
+ 	}
+ 
+ 	bnx2x_prepare_xmit_packet(nic, nic_iface, pkt);
+-	bnx2x_start_xmit(nic, pkt->buf_size, nic_iface->vlan_id);
++	bnx2x_start_xmit(nic, pkt->buf_size,
++			 (nic_iface->vlan_priority << 12) |
++			 nic_iface->vlan_id);
+ 
+ 	/*  bump the cnic dev send statistics */
+ 	nic->stats.tx.packets++;
+ 	nic->stats.tx.bytes += uip->uip_len;
+ 
+-	LOG_DEBUG(PFX "%s: transmitted %d bytes "
+-		  "dev->tx_cons: %d, dev->tx_prod: %d, dev->tx_bd_prod:%d",
+-		  nic->log_name, pkt->buf_size,
+-		  bp->tx_cons, bp->tx_prod, bp->tx_bd_prod);
++	LOG_PACKET(PFX "%s: transmitted %d bytes "
++		   "dev->tx_cons: %d, dev->tx_prod: %d, dev->tx_bd_prod:%d",
++		   nic->log_name, pkt->buf_size,
++		   bp->tx_cons, bp->tx_prod, bp->tx_bd_prod);
+ 
+ 	return 0;
+ }
+@@ -1348,7 +1378,7 @@ static inline int bnx2x_get_rx_pad(bnx2x_t * bp, union eth_rx_cqe *cqe)
+  */
+ static int bnx2x_read(nic_t * nic, packet_t * pkt)
+ {
+-	bnx2x_t *bp = (bnx2x_t *) nic->priv;
++	bnx2x_t *bp;
+ 	int rc = 0;
+ 	uint16_t hw_cons, sw_cons, bd_cons, bd_prod;
+ 
+@@ -1358,6 +1388,7 @@ static int bnx2x_read(nic_t * nic, packet_t * pkt)
+ 			" pkt == 0x%x", nic, pkt);
+ 		return -EINVAL;
+ 	}
++	bp = (bnx2x_t *) nic->priv;
+ 
+ 	hw_cons = bp->get_rx_cons(bp);
+ 	sw_cons = bp->rx_cons;
+@@ -1383,8 +1414,8 @@ static int bnx2x_read(nic_t * nic, packet_t * pkt)
+ 		}
+ 		cqe_fp_flags = cqe->fast_path_cqe.type_error_flags;
+ 
+-		LOG_DEBUG(PFX "%s: clearing rx interrupt: %d %d",
+-			  nic->log_name, sw_cons, hw_cons);
++		LOG_PACKET(PFX "%s: clearing rx interrupt: %d %d",
++			   nic->log_name, sw_cons, hw_cons);
+ 
+ 		msync(cqe, cqe_size, MS_SYNC);
+ 
+@@ -1416,9 +1447,9 @@ static int bnx2x_read(nic_t * nic, packet_t * pkt)
+ 					pkt->vlan_tag = 0;
+ 				}
+ 
+-				LOG_DEBUG(PFX
+-					  "%s: processing packet length: %d",
+-					  nic->log_name, len);
++				LOG_PACKET(PFX
++					   "%s: processing packet length: %d",
++					   nic->log_name, len);
+ 
+ 				/*  bump the cnic dev recv statistics */
+ 				nic->stats.rx.packets++;
+@@ -1453,14 +1484,16 @@ static int bnx2x_read(nic_t * nic, packet_t * pkt)
+  */
+ static int bnx2x_clear_tx_intr(nic_t * nic)
+ {
+-	bnx2x_t *bp = (bnx2x_t *) nic->priv;
+-	uint16_t hw_cons = bp->get_tx_cons(bp);
++	bnx2x_t *bp;
++	uint16_t hw_cons;
+ 
+ 	/* Sanity check: ensure the parameters passed in are valid */
+ 	if (unlikely(nic == NULL)) {
+ 		LOG_ERR(PFX "bnx2x_read() nic == NULL");
+ 		return -EINVAL;
+ 	}
++	bp = (bnx2x_t *) nic->priv;
++	hw_cons = bp->get_tx_cons(bp);
+ 
+ 	if (bp->tx_cons == hw_cons) {
+ 		if (bp->tx_cons == bp->tx_prod) {
+@@ -1473,8 +1506,8 @@ static int bnx2x_clear_tx_intr(nic_t * nic)
+ 		return -EAGAIN;
+ 	}
+ 
+-	LOG_DEBUG(PFX "%s: clearing tx interrupt [%d %d]",
+-		  nic->log_name, bp->tx_cons, hw_cons);
++	LOG_PACKET(PFX "%s: clearing tx interrupt [%d %d]",
++		   nic->log_name, bp->tx_cons, hw_cons);
+ 	bp->tx_cons = hw_cons;
+ 
+ 	/*  There is a queued TX packet that needs to be sent out.  The usual
+@@ -1484,7 +1517,7 @@ static int bnx2x_clear_tx_intr(nic_t * nic)
+ 		packet_t *pkt;
+ 		int i;
+ 
+-		LOG_DEBUG(PFX "%s: sending queued tx packet", nic->log_name);
++		LOG_PACKET(PFX "%s: sending queued tx packet", nic->log_name);
+ 		pkt = nic_dequeue_tx_packet(nic);
+ 
+ 		/*  Got a TX packet buffer of the TX queue and put it onto
+@@ -1493,13 +1526,14 @@ static int bnx2x_clear_tx_intr(nic_t * nic)
+ 			bnx2x_prepare_xmit_packet(nic, pkt->nic_iface, pkt);
+ 
+ 			bnx2x_start_xmit(nic, pkt->buf_size,
++					 (pkt->nic_iface->vlan_priority << 12) |
+ 					 pkt->nic_iface->vlan_id);
+ 
+-			LOG_DEBUG(PFX "%s: transmitted queued packet %d bytes "
+-				  "dev->tx_cons: %d, dev->tx_prod: %d, "
+-				  "dev->tx_bd_prod:%d",
+-				  nic->log_name, pkt->buf_size,
+-				  bp->tx_cons, bp->tx_prod, bp->tx_bd_prod);
++			LOG_PACKET(PFX "%s: transmitted queued packet %d bytes "
++				   "dev->tx_cons: %d, dev->tx_prod: %d, "
++				   "dev->tx_bd_prod:%d",
++				   nic->log_name, pkt->buf_size,
++				   bp->tx_cons, bp->tx_prod, bp->tx_bd_prod);
+ 
+ 			return 0;
+ 		}
+@@ -1512,9 +1546,9 @@ static int bnx2x_clear_tx_intr(nic_t * nic)
+ 
+ 			hw_cons = bp->get_tx_cons(bp);
+ 			if (bp->tx_cons != hw_cons) {
+-				LOG_DEBUG(PFX
+-					  "%s: clearing tx interrupt [%d %d]",
+-					  nic->log_name, bp->tx_cons, hw_cons);
++				LOG_PACKET(PFX
++					   "%s: clearing tx interrupt [%d %d]",
++					   nic->log_name, bp->tx_cons, hw_cons);
+ 				bp->tx_cons = hw_cons;
+ 
+ 				break;
+diff --git a/src/unix/libs/bnx2x.h b/src/unix/libs/bnx2x.h
+index 8e923b9..b758179 100644
+--- a/src/unix/libs/bnx2x.h
++++ b/src/unix/libs/bnx2x.h
+@@ -467,6 +467,18 @@ struct client_init_general_data {
+ #define BAR_XSTRORM_INTMEM				0x420000
+ #define BAR_TSTRORM_INTMEM				0x430000
+ 
++#define BAR_ME_REGISTER					0x450000
++#define ME_REG_PF_NUM_SHIFT		0
++#define ME_REG_PF_NUM\
++	(7L<<ME_REG_PF_NUM_SHIFT) /* Relative PF Num */
++#define ME_REG_VF_VALID			(1<<8)
++#define ME_REG_VF_NUM_SHIFT		9
++#define ME_REG_VF_NUM_MASK		(0x3f<<ME_REG_VF_NUM_SHIFT)
++#define ME_REG_VF_ERR			(0x1<<3)
++#define ME_REG_ABS_PF_NUM_SHIFT		16
++#define ME_REG_ABS_PF_NUM\
++	(7L<<ME_REG_ABS_PF_NUM_SHIFT) /* Absolute PF Num */
++
+ #define USTORM_RX_PRODS_OFFSET(port, client_id) \
+ 	(IS_E1H_OFFSET ? (0x1000 + (port * 0x680) + (client_id * 0x40)) \
+ 	: (0x4000 + (port * 0x360) + (client_id * 0x30)))
+diff --git a/src/unix/libs/cnic.c b/src/unix/libs/cnic.c
+index 841c1ac..a81d47b 100644
+--- a/src/unix/libs/cnic.c
++++ b/src/unix/libs/cnic.c
+@@ -125,6 +125,7 @@ static int cnic_arp_send(nic_t * nic, nic_interface_t * nic_iface, int fd,
+ 	memcpy(arp->arp_tpa, &dst_ip, 4);
+ 
+ 	(*nic->nic_library->ops->start_xmit) (nic, pkt_size,
++					      (nic_iface->vlan_priority << 12) |
+ 					      nic_iface->vlan_id);
+ 
+ 	memcpy(&addr.s_addr, &dst_ip, sizeof(addr.s_addr));
+@@ -166,15 +167,6 @@ static int cnic_neigh_soliciation_send(nic_t * nic,
+ 	memcpy(ipv6_hdr->ip6_dst.s6_addr, addr6_dst->s6_addr,
+ 	       sizeof(struct in6_addr));
+ 
+-	LOG_DEBUG(PFX "dst ip addr %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
+-		  ipv6_hdr->ip6_dst.s6_addr16[0],
+-		  ipv6_hdr->ip6_dst.s6_addr16[1],
+-		  ipv6_hdr->ip6_dst.s6_addr16[2],
+-		  ipv6_hdr->ip6_dst.s6_addr16[3],
+-		  ipv6_hdr->ip6_dst.s6_addr16[4],
+-		  ipv6_hdr->ip6_dst.s6_addr16[5],
+-		  ipv6_hdr->ip6_dst.s6_addr16[6],
+-		  ipv6_hdr->ip6_dst.s6_addr16[7]);
+ 	nic_fill_ethernet_header(nic_iface, eth, nic->mac_addr, nic->mac_addr,
+ 				 &pkt_size, (void *)&ipv6_hdr, ETHERTYPE_IPV6);
+ 	req_ptr.eth = (void *)eth;
+@@ -196,6 +188,7 @@ static int cnic_neigh_soliciation_send(nic_t * nic,
+ 		  eth->ether_shost[2], eth->ether_shost[3],
+ 		  eth->ether_shost[4], eth->ether_shost[5]);
+ 	(*nic->nic_library->ops->start_xmit) (nic, pkt_size,
++					      (nic_iface->vlan_priority << 12) |
+ 					      nic_iface->vlan_id);
+ 
+ 	LOG_DEBUG(PFX "%s: Sent cnic ICMPv6 neighbor request %s",
+@@ -261,12 +254,7 @@ static int cnic_nl_neigh_rsp(nic_t * nic, int fd,
+ 		}
+ 		if (ret) {
+ 			/* Get link local IPv6 address */
+-			if (ndpc_request(&nic_iface->ustack, NULL,
+-					 &src_ipv6, GET_LINK_LOCAL_ADDR)) {
+-				src_ipv6 = (u8_t *)all_zeroes_addr6;
+-				LOG_DEBUG(PFX "RSP Get LL failed");
+-				goto src_done;
+-			}
++			src_ipv6 = (u8_t *)&nic_iface->ustack.linklocal6;
+ 		} else {
+ 			if (ndpc_request(&nic_iface->ustack,
+ 					 &path_req->dst.v6_addr,
+@@ -288,16 +276,18 @@ src_done:
+ 			  addr_dst_str, sizeof(addr_dst_str));
+ 	}
+ 	memcpy(path_rsp->mac_addr, mac_addr, 6);
+-	path_rsp->vlan_id = path_req->vlan_id;
+-	path_rsp->pmtu = path_req->pmtu;
++	path_rsp->vlan_id = (nic_iface->vlan_priority << 12) |
++			    nic_iface->vlan_id;
++	path_rsp->pmtu = nic_iface->mtu ? nic_iface->mtu : path_req->pmtu;
+ 
+ 	rc = __kipc_call(fd, ret_ev, sizeof(*ret_ev) + sizeof(*path_rsp));
+ 	if (rc > 0) {
+ 		LOG_DEBUG(PFX "neighbor reply sent back to kernel "
+-			  "%s at %02x:%02x:%02x:%02x:%02x:%02x",
++			  "%s at %02x:%02x:%02x:%02x:%02x:%02x with vlan %d",
+ 			  addr_dst_str,
+ 			  mac_addr[0], mac_addr[1],
+-			  mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
++			  mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5],
++			  nic_iface->vlan_id);
+ 
+ 	} else {
+ 		LOG_ERR(PFX "send neighbor reply failed: %d", rc);
+@@ -323,67 +313,18 @@ const static struct timeval tp_wait = {
+  */
+ int cnic_handle_ipv4_iscsi_path_req(nic_t * nic, int fd,
+ 				    struct iscsi_uevent *ev,
+-				    struct iscsi_path *path)
++				    struct iscsi_path *path,
++				    nic_interface_t *nic_iface)
+ {
+-	nic_interface_t *nic_iface, *vlan_iface;
+ 	struct in_addr src_addr, dst_addr,
+ 	    src_matching_addr, dst_matching_addr, netmask;
+ 	__u8 mac_addr[6];
+ 	int rc;
+ 	uint16_t arp_retry;
+ 	int status = 0;
+-
+-	memset(mac_addr, 0, sizeof(mac_addr));
+-
+-	pthread_mutex_lock(&nic_list_mutex);
+-
+-	/*  Find the proper interface via VLAN id */
+-	nic_iface = nic_find_nic_iface_protocol(nic, 0, AF_INET);
+-	if (nic_iface == NULL) {
+-		pthread_mutex_unlock(&nic_list_mutex);
+-		LOG_ERR(PFX "%s: Couldn't find net_iface vlan_id: %d",
+-			nic->log_name, path->vlan_id);
+-		return -EINVAL;
+-	}
+-	if (path->vlan_id) {
+-		vlan_iface = nic_find_vlan_iface_protocol(nic, nic_iface,
+-							  path->vlan_id,
+-							  AF_INET);
+-		if (vlan_iface == NULL) {
+-			LOG_INFO(PFX "%s couldn't find interface with VLAN = %d"
+-				 "ip_type: 0x%x creating it",
+-				 nic->log_name, path->vlan_id, AF_INET);
+-
+-			/*  Create the nic interface */
+-			vlan_iface = nic_iface_init();
+-
+-			if (vlan_iface == NULL) {
+-				LOG_ERR(PFX "Couldn't allocate nic_iface for "
+-					"VLAN: %d", vlan_iface,
+-					path->vlan_id);
+-				return -EINVAL;
+-			}
+-
+-			vlan_iface->protocol = nic_iface->protocol;
+-			vlan_iface->vlan_id = path->vlan_id;
+-			vlan_iface->ustack.ip_config =
+-						nic_iface->ustack.ip_config;
+-			memcpy(vlan_iface->ustack.hostaddr,
+-			       nic_iface->ustack.hostaddr,
+-			       sizeof(nic_iface->ustack.hostaddr));
+-			memcpy(vlan_iface->ustack.netmask,
+-			       nic_iface->ustack.netmask,
+-			       sizeof(nic_iface->ustack.netmask));
+-			nic_add_vlan_iface(nic, nic_iface, vlan_iface);
+-		} else {
+-			LOG_INFO(PFX "%s: using existing vlan interface",
+-				 nic->log_name);
+-		}
+-		nic_iface = vlan_iface;
+-	}
+-
+ #define MAX_ARP_RETRY 4
+ 
++	memset(mac_addr, 0, sizeof(mac_addr));
+ 	memcpy(&dst_addr, &path->dst.v4_addr, sizeof(dst_addr));
+ 	memcpy(&src_addr, nic_iface->ustack.hostaddr, sizeof(src_addr));
+ 
+@@ -445,20 +386,15 @@ int cnic_handle_ipv4_iscsi_path_req(nic_t * nic, int fd,
+ 				ts.tv_sec = tp_abs.tv_sec;
+ 				ts.tv_nsec = tp_abs.tv_usec * 1000;
+ 
+-				pthread_mutex_unlock(&nic_list_mutex);
++				/* Wait 1s for if_down */
++				pthread_mutex_lock(&nic->nl_process_mutex);
+ 				rc = pthread_cond_timedwait
+-				    (&nl_process_if_down_cond,
+-				     &nl_process_mutex, &ts);
++						(&nic->nl_process_if_down_cond,
++						 &nic->nl_process_mutex, &ts);
+ 
+ 				if (rc == ETIMEDOUT) {
+-					pthread_mutex_unlock(&nl_process_mutex);
+-
+-					if (pthread_mutex_trylock
+-					    (&nic_list_mutex) != 0) {
+-						arp_retry = MAX_ARP_RETRY;
+-						goto done;
+-
+-					}
++					pthread_mutex_unlock
++						(&nic->nl_process_mutex);
+ 
+ 					rc = uip_lookup_arp_entry(dst_addr.
+ 								  s_addr,
+@@ -466,8 +402,9 @@ int cnic_handle_ipv4_iscsi_path_req(nic_t * nic, int fd,
+ 					if (rc == 0)
+ 						goto done;
+ 				} else {
+-					nl_process_if_down = 0;
+-					pthread_mutex_unlock(&nl_process_mutex);
++					nic->nl_process_if_down = 0;
++					pthread_mutex_unlock
++						(&nic->nl_process_mutex);
+ 
+ 					arp_retry = MAX_ARP_RETRY;
+ 					goto done;
+@@ -491,9 +428,6 @@ done:
+ 
+ 	cnic_nl_neigh_rsp(nic, fd, ev, path, mac_addr,
+ 			  nic_iface, status, AF_INET);
+-
+-	pthread_mutex_unlock(&nic_list_mutex);
+-
+ 	return rc;
+ }
+ 
+@@ -507,9 +441,9 @@ done:
+  */
+ int cnic_handle_ipv6_iscsi_path_req(nic_t * nic, int fd,
+ 				    struct iscsi_uevent *ev,
+-				    struct iscsi_path *path)
++				    struct iscsi_path *path,
++				    nic_interface_t *nic_iface)
+ {
+-	nic_interface_t *nic_iface, *vlan_iface;
+ 	__u8 mac_addr[6];
+ 	int rc, i;
+ 	uint16_t neighbor_retry;
+@@ -525,52 +459,6 @@ int cnic_handle_ipv6_iscsi_path_req(nic_t * nic, int fd,
+ 	inet_ntop(AF_INET6, &path->dst.v6_addr,
+ 		  addr_dst_str, sizeof(addr_dst_str));
+ 
+-	pthread_mutex_lock(&nic_list_mutex);
+-
+-	/*  Find the proper interface via VLAN id */
+-	nic_iface = nic_find_nic_iface_protocol(nic, 0, AF_INET6);
+-	if (nic_iface == NULL) {
+-		pthread_mutex_unlock(&nic_list_mutex);
+-		LOG_ERR(PFX "%s: Couldn't find net_iface vlan_id: %d",
+-			nic->log_name, path->vlan_id);
+-		return -EINVAL;
+-	}
+-	if (path->vlan_id) {
+-		vlan_iface = nic_find_vlan_iface_protocol(nic, nic_iface,
+-							  path->vlan_id,
+-							  AF_INET6);
+-		if (vlan_iface == NULL) {
+-			LOG_INFO(PFX "%s couldn't find interface with VLAN = %d"
+-				 "ip_type: 0x%x creating it",
+-				 nic->log_name, path->vlan_id, AF_INET6);
+-
+-			/*  Create the nic interface */
+-			vlan_iface = nic_iface_init();
+-
+-			if (vlan_iface == NULL) {
+-				LOG_ERR(PFX "Couldn't allocate nic_iface for "
+-					"VLAN: %d", vlan_iface,
+-					path->vlan_id);
+-				return -EINVAL;
+-			}
+-			vlan_iface->protocol = nic_iface->protocol;
+-			vlan_iface->vlan_id = path->vlan_id;
+-			vlan_iface->ustack.ip_config =
+-						nic_iface->ustack.ip_config;
+-			memcpy(vlan_iface->ustack.hostaddr6,
+-			       nic_iface->ustack.hostaddr6,
+-			       sizeof(nic_iface->ustack.hostaddr6));
+-			memcpy(vlan_iface->ustack.netmask6,
+-			       nic_iface->ustack.netmask6,
+-			       sizeof(nic_iface->ustack.netmask6));
+-			nic_add_vlan_iface(nic, nic_iface, vlan_iface);
+-		} else {
+-			LOG_INFO(PFX "%s: using existing vlan interface",
+-				 nic->log_name);
+-		}
+-		nic_iface = vlan_iface;
+-	}
+-
+ 	/*  Depending on the IPv6 address of the target we will need to
+ 	 *  determine whether we use the assigned IPv6 address or the
+ 	 *  link local IPv6 address */
+@@ -584,12 +472,7 @@ int cnic_handle_ipv6_iscsi_path_req(nic_t * nic, int fd,
+ 	if (rc) {
+ 		LOG_DEBUG(PFX "Use LL");
+ 		/* Get link local IPv6 address */
+-		if (ndpc_request(&nic_iface->ustack, NULL,
+-				 &addr, GET_LINK_LOCAL_ADDR)) {
+-			neighbor_retry = MAX_ARP_RETRY;
+-			LOG_DEBUG(PFX "Use LL failed");
+-			goto done;
+-		}
++		addr = (struct in6_addr *)&nic_iface->ustack.linklocal6;
+ 	} else {
+ 		LOG_DEBUG(PFX "Use Best matched");
+ 		if (ndpc_request(&nic_iface->ustack,
+@@ -618,21 +501,15 @@ int cnic_handle_ipv6_iscsi_path_req(nic_t * nic, int fd,
+ 		memcpy(&netmask.s6_addr, all_zeroes_addr6,
+ 		       sizeof(struct in6_addr));
+ 
+-	LOG_DEBUG(PFX "src addr %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
+-		  src_addr.s6_addr16[0], src_addr.s6_addr16[1],
+-		  src_addr.s6_addr16[2], src_addr.s6_addr16[3],
+-		  src_addr.s6_addr16[4], src_addr.s6_addr16[5],
+-		  src_addr.s6_addr16[6], src_addr.s6_addr16[7]);
+-	LOG_DEBUG(PFX "dst addr %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
+-		  dst_addr.s6_addr16[0], dst_addr.s6_addr16[1],
+-		  dst_addr.s6_addr16[2], dst_addr.s6_addr16[3],
+-		  dst_addr.s6_addr16[4], dst_addr.s6_addr16[5],
+-		  dst_addr.s6_addr16[6], dst_addr.s6_addr16[7]);
+-	LOG_DEBUG(PFX "nm addr %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
+-		  netmask.s6_addr16[0], netmask.s6_addr16[1],
+-		  netmask.s6_addr16[2], netmask.s6_addr16[3],
+-		  netmask.s6_addr16[4], netmask.s6_addr16[5],
+-		  netmask.s6_addr16[6], netmask.s6_addr16[7]);
++	inet_ntop(AF_INET6, &src_addr.s6_addr16, addr_dst_str,
++		  sizeof(addr_dst_str));
++	LOG_DEBUG(PFX "src IP addr %s", addr_dst_str);
++	inet_ntop(AF_INET6, &dst_addr.s6_addr16, addr_dst_str,
++		  sizeof(addr_dst_str));
++	LOG_DEBUG(PFX "dst IP addr %s", addr_dst_str);
++	inet_ntop(AF_INET6, &netmask.s6_addr16, addr_dst_str,
++		  sizeof(addr_dst_str));
++	LOG_DEBUG(PFX "prefix mask %s", addr_dst_str);
+ 
+ 	for (i = 0; i < 4; i++) {
+ 		src_matching_addr.s6_addr32[i] = src_addr.s6_addr32[i] &
+@@ -642,24 +519,22 @@ int cnic_handle_ipv6_iscsi_path_req(nic_t * nic, int fd,
+ 		if (src_matching_addr.s6_addr32[i] !=
+ 		    dst_matching_addr.s6_addr32[i]) {
+ 			/* No match with the prefix mask, use default route */
+-			if (ndpc_request(&nic_iface->ustack, NULL, &addr,
+-					 GET_DEFAULT_ROUTER_ADDR)) {
+-				neighbor_retry = MAX_ARP_RETRY;
+-				goto done;
+-			}
+-			if (memcmp(addr, all_zeroes_addr6, sizeof(*addr)))
+-				memcpy(&dst_addr, addr, sizeof(dst_addr));
+-			else {
++			if (memcmp(nic_iface->ustack.default_route_addr6,
++				   all_zeroes_addr6, sizeof(*addr))) {
++				memcpy(&dst_addr,
++				       nic_iface->ustack.default_route_addr6,
++				       sizeof(dst_addr));
++				inet_ntop(AF_INET6, &dst_addr.s6_addr16,
++					  addr_dst_str, sizeof(addr_dst_str));
++				LOG_DEBUG(PFX "Use default router IP addr %s",
++					  addr_dst_str);
++				break;
++			} else {
+ 				neighbor_retry = MAX_ARP_RETRY;
+ 				goto done;
+ 			}
+ 		}
+ 	}
+-	LOG_DEBUG(PFX "dst addr %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
+-		  dst_addr.s6_addr16[0], dst_addr.s6_addr16[1],
+-		  dst_addr.s6_addr16[2], dst_addr.s6_addr16[3],
+-		  dst_addr.s6_addr16[4], dst_addr.s6_addr16[5],
+-		  dst_addr.s6_addr16[6], dst_addr.s6_addr16[7]);
+ 
+ #define MAX_ARP_RETRY 4
+ 	neighbor_retry = 0;
+@@ -672,6 +547,8 @@ int cnic_handle_ipv6_iscsi_path_req(nic_t * nic, int fd,
+ 		goto done;
+ 	}
+ 	if (!rc) {
++		inet_ntop(AF_INET6, &dst_addr.s6_addr16,
++			  addr_dst_str, sizeof(addr_dst_str));
+ 		LOG_DEBUG(PFX
+ 			  "%s: Preparing to send IPv6 neighbor solicitation "
+ 			  "to dst: '%s'", nic->log_name, addr_dst_str);
+@@ -703,20 +580,14 @@ int cnic_handle_ipv6_iscsi_path_req(nic_t * nic, int fd,
+ 				ts.tv_sec = tp_abs.tv_sec;
+ 				ts.tv_nsec = tp_abs.tv_usec * 1000;
+ 
+-				pthread_mutex_unlock(&nic_list_mutex);
++				pthread_mutex_lock(&nic->nl_process_mutex);
+ 				rc = pthread_cond_timedwait
+-				    (&nl_process_if_down_cond,
+-				     &nl_process_mutex, &ts);
++				    (&nic->nl_process_if_down_cond,
++				     &nic->nl_process_mutex, &ts);
+ 
+ 				if (rc == ETIMEDOUT) {
+-					pthread_mutex_unlock(&nl_process_mutex);
+-
+-					if (pthread_mutex_trylock
+-					    (&nic_list_mutex) != 0) {
+-						neighbor_retry = MAX_ARP_RETRY;
+-						goto done;
+-
+-					}
++					pthread_mutex_unlock
++						(&nic->nl_process_mutex);
+ 
+ 					req_ptr.eth = (void *)mac_addr;
+ 					req_ptr.ipv6 = (void *)&dst_addr;
+@@ -730,8 +601,9 @@ int cnic_handle_ipv6_iscsi_path_req(nic_t * nic, int fd,
+ 					if (rc)
+ 						goto done;
+ 				} else {
+-					nl_process_if_down = 0;
+-					pthread_mutex_unlock(&nl_process_mutex);
++					nic->nl_process_if_down = 0;
++					pthread_mutex_unlock
++						(&nic->nl_process_mutex);
+ 
+ 					neighbor_retry = MAX_ARP_RETRY;
+ 					goto done;
+@@ -752,9 +624,6 @@ done:
+ 
+ 	cnic_nl_neigh_rsp(nic, fd, ev, path, mac_addr,
+ 			  nic_iface, status, AF_INET6);
+-
+-	pthread_mutex_unlock(&nic_list_mutex);
+-
+ 	return rc;
+ }
+ 
+@@ -764,11 +633,12 @@ done:
+  * @param nic - The nic the message is directed towards
+  * @param fd  - The file descriptor to be used to extract the private data
+  * @param ev  - The iscsi_uevent
+- * @param buf - The private message buffer
+- * @param buf_len - The private message buffer length
++ * @param path - The private message buffer
++ * @param nic_iface - The nic_iface to use for this connection request
+  */
+ int cnic_handle_iscsi_path_req(nic_t * nic, int fd, struct iscsi_uevent *ev,
+-			       struct iscsi_path *path)
++			       struct iscsi_path *path,
++			       nic_interface_t *nic_iface)
+ {
+ 
+ 	LOG_DEBUG(PFX "%s: Netlink message with VLAN ID: %d, path MTU: %d "
+@@ -777,9 +647,11 @@ int cnic_handle_iscsi_path_req(nic_t * nic, int fd, struct iscsi_uevent *ev,
+ 		  path->ip_addr_len);
+ 
+ 	if (path->ip_addr_len == 4)
+-		return cnic_handle_ipv4_iscsi_path_req(nic, fd, ev, path);
++		return cnic_handle_ipv4_iscsi_path_req(nic, fd, ev, path,
++						       nic_iface);
+ 	else if (path->ip_addr_len == 16)
+-		return cnic_handle_ipv6_iscsi_path_req(nic, fd, ev, path);
++		return cnic_handle_ipv6_iscsi_path_req(nic, fd, ev, path,
++						       nic_iface);
+ 	else {
+ 		LOG_DEBUG(PFX "%s: unknown ip_addr_len: %d size dropping ",
+ 			  nic->log_name, path->ip_addr_len);
+diff --git a/src/unix/libs/cnic.h b/src/unix/libs/cnic.h
+index 738deb8..679dab8 100644
+--- a/src/unix/libs/cnic.h
++++ b/src/unix/libs/cnic.h
+@@ -48,6 +48,7 @@ int cnic_nl_open();
+ void cnic_nl_close();
+ 
+ int cnic_handle_iscsi_path_req(nic_t * nic, int, struct iscsi_uevent *,
+-			       struct iscsi_path *path);
++			       struct iscsi_path *path,
++			       nic_interface_t *nic_iface);
+ 
+ #endif /* __CNIC_NL_H__ */
+diff --git a/src/unix/main.c b/src/unix/main.c
+index 4f548e9..2008913 100644
+--- a/src/unix/main.c
++++ b/src/unix/main.c
+@@ -141,7 +141,6 @@ signal_wait:
+ 		break;
+ 	case SIGUSR1:
+ 		LOG_INFO("Caught SIGUSR1 signal, rotate log");
+-retry:
+ 		fini_logger(SHUTDOWN_LOGGER);
+ 		rc = init_logger(main_log.log_file);
+ 		if (rc != 0)
+diff --git a/src/unix/nic.c b/src/unix/nic.c
+index 0934b56..0b3c538 100644
+--- a/src/unix/nic.c
++++ b/src/unix/nic.c
+@@ -64,6 +64,7 @@
+ 
+ #include "bnx2.h"
+ #include "bnx2x.h"
++#include "ipv6.h"
+ 
+ /******************************************************************************
+  *  Constants
+@@ -118,7 +119,7 @@ static void free_nic_library_handle(nic_lib_handle_t * handle)
+  *  @param handle - This is the library handle to load
+  *  @return 0 = Success; <0 = failure
+  */
+-static int load_nic_library(nic_lib_handle_t * handle)
++static int load_nic_library(nic_lib_handle_t *handle)
+ {
+ 	int rc;
+ 	char *library_name;
+@@ -172,7 +173,7 @@ static int load_nic_library(nic_lib_handle_t * handle)
+ 
+ 	return 0;
+ 
+-      error:
++error:
+ 	pthread_mutex_unlock(&handle->mutex);
+ 
+ 	return rc;
+@@ -197,9 +198,10 @@ int load_all_nic_libraries()
+ 		handle->ops = (*nic_get_ops[i]) ();
+ 
+ 		rc = load_nic_library(handle);
+-		if (rc != 0)
++		if (rc != 0) {
++			free_nic_library_handle(handle);
+ 			return rc;
+-
++		}
+ 		/*  Add the CNIC library to the list of library handles */
+ 		pthread_mutex_lock(&nic_lib_list_mutex);
+ 
+@@ -270,7 +272,7 @@ NIC_LIBRARY_EXIST_T does_nic_uio_name_exist(char *name)
+ 
+ 	rc = NIC_LIBRARY_DOESNT_EXIST;
+ 
+-      done:
++done:
+ 	pthread_mutex_unlock(&nic_lib_list_mutex);
+ 	return rc;
+ }
+@@ -300,7 +302,7 @@ NIC_LIBRARY_EXIST_T does_nic_library_exist(char *name)
+ 
+ 	rc = NIC_LIBRARY_DOESNT_EXIST;
+ 
+-      done:
++done:
+ 	pthread_mutex_unlock(&nic_lib_list_mutex);
+ 	return rc;
+ }
+@@ -366,7 +368,7 @@ int find_nic_lib_using_pci_id(uint32_t vendor, uint32_t device,
+ 	}
+ 	rc = -EINVAL;
+ 
+-      done:
++done:
+ 	pthread_mutex_unlock(&nic_lib_list_mutex);
+ 
+ 	return rc;
+@@ -393,13 +395,14 @@ nic_t *nic_init()
+ 	nic->next = NULL;
+ 	nic->thread = INVALID_THREAD;
+ 	nic->enable_thread = INVALID_THREAD;
+-	nic->flags |= NIC_UNITIALIZED | NIC_DISABLED;
+-	nic->state |= NIC_STOPPED;
++	nic->flags |= NIC_DISABLED;
++	nic->state = NIC_STOPPED;
+ 	nic->free_packet_queue = NULL;
+ 	nic->tx_packet_queue = NULL;
+ 	nic->nic_library = NULL;
+ 	nic->pci_id = NULL;
+ 
++	/* nic_mutex is used to protect nic_ops */
+ 	pthread_mutex_init(&nic->nic_mutex, NULL);
+ 	pthread_mutex_init(&nic->xmit_mutex, NULL);
+ 	pthread_mutex_init(&nic->free_packet_queue_mutex, NULL);
+@@ -411,6 +414,15 @@ nic_t *nic_init()
+ 
+ 	nic->rx_poll_usec = DEFAULT_RX_POLL_USEC;
+ 
++	pthread_mutex_init(&nic->nl_process_mutex, NULL);
++	pthread_cond_init(&nic->nl_process_if_down_cond, NULL);
++	pthread_cond_init(&nic->nl_process_cond, NULL);
++	nic->nl_process_thread = INVALID_THREAD;
++	nic->nl_process_if_down = 0;
++	nic->nl_process_head = 0;
++	nic->nl_process_tail = 0;
++	memset(&nic->nl_process_ring, 0, sizeof(nic->nl_process_ring));
++
+ 	return nic;
+ }
+ 
+@@ -432,7 +444,6 @@ void nic_add(nic_t * nic)
+ 
+ /** 
+  *  nic_remove() - Used to remove the NIC for the nic list
+-                   nic_list_mutex must be taken
+  *  @param nic - the nic to remove
+  */
+ int nic_remove(nic_t * nic)
+@@ -451,41 +462,66 @@ int nic_remove(nic_t * nic)
+ 		nic->ops->close(nic, 0);
+ 
+ 	nic->state = NIC_EXIT;
+-	pthread_mutex_unlock(&nic->nic_mutex);
+ 
+ 	if (nic->enable_thread != INVALID_THREAD) {
+-		LOG_ERR(PFX "%s: Canceling nic enable thread", nic->log_name);
++		LOG_DEBUG(PFX "%s: Canceling nic enable thread", nic->log_name);
+ 
+ 		rc = pthread_cancel(nic->enable_thread);
+ 		if (rc != 0)
+-			LOG_ERR(PFX "%s: Couldn't send cancel to nic enable "
+-				"thread", nic->log_name);
++			LOG_DEBUG(PFX "%s: Couldn't send cancel to nic enable "
++				  "thread", nic->log_name);
+ 
+-		LOG_ERR(PFX "%s: Waiting to join nic enable thread",
+-			nic->log_name);
++		LOG_DEBUG(PFX "%s: Waiting to join nic enable thread",
++			  nic->log_name);
+ 		rc = pthread_join(nic->enable_thread, &res);
+ 		if (rc != 0)
+-			LOG_ERR(PFX "%s: Couldn't join to canceled enable nic "
+-				"thread", nic->log_name);
++			LOG_DEBUG(PFX "%s: Couldn't join to canceled enable "
++				  "nic thread", nic->log_name);
+ 		nic->enable_thread = INVALID_THREAD;
++		LOG_DEBUG(PFX "%s: nic enable thread cleaned", nic->log_name);
++	} else {
++		LOG_DEBUG(PFX "%s: NIC enable thread already canceled",
++			  nic->log_name);
+ 	}
++
+ 	if (nic->thread != INVALID_THREAD) {
+-		LOG_ERR(PFX "%s: Canceling nic thread", nic->log_name);
++		LOG_DEBUG(PFX "%s: Canceling nic thread", nic->log_name);
+ 
+ 		rc = pthread_cancel(nic->thread);
+ 		if (rc != 0)
+-			LOG_ERR(PFX "%s: Couldn't send cancel to nic",
+-				nic->log_name);
++			LOG_DEBUG(PFX "%s: Couldn't send cancel to nic",
++				  nic->log_name);
+ 
+-		LOG_ERR(PFX "%s: Waiting to join nic thread", nic->log_name);
++		LOG_DEBUG(PFX "%s: Waiting to join nic thread", nic->log_name);
+ 		rc = pthread_join(nic->thread, &res);
+ 		if (rc != 0)
+-			LOG_ERR(PFX "%s: Couldn't join to canceled nic thread",
+-				nic->log_name);
+-
++			LOG_DEBUG(PFX "%s: Couldn't join to canceled nic "
++				  "thread", nic->log_name);
+ 		nic->thread = INVALID_THREAD;
++		LOG_DEBUG(PFX "%s: nic thread cleaned", nic->log_name);
++	} else {
++		LOG_DEBUG(PFX "%s: NIC thread already canceled", nic->log_name);
++	}
++
++	if (nic->nl_process_thread != INVALID_THREAD) {
++		LOG_DEBUG(PFX "%s: Canceling nic nl thread", nic->log_name);
++
++		rc = pthread_cancel(nic->nl_process_thread);
++		if (rc != 0)
++			LOG_DEBUG(PFX "%s: Couldn't send cancel to nic nl "
++				  "thread", nic->log_name);
++
++		LOG_DEBUG(PFX "%s: Waiting to join nic nl thread",
++			  nic->log_name);
++		rc = pthread_join(nic->nl_process_thread, &res);
++		if (rc != 0)
++			LOG_DEBUG(PFX "%s: Couldn't join to canceled nic nl "
++				  "thread", nic->log_name);
++		nic->nl_process_thread = INVALID_THREAD;
++		LOG_DEBUG(PFX "%s: nic nl thread cleaned", nic->log_name);
+ 	} else {
+-		LOG_ERR(PFX "%s: NIC thread already canceled", nic->log_name);
++		LOG_DEBUG(PFX "%s: NIC nl thread already canceled",
++			  nic->log_name);
+ 	}
+ 
+ 	current = prev = nic_list;
+@@ -505,7 +541,7 @@ int nic_remove(nic_t * nic)
+ 
+ 		/* Before freeing the nic, must free all the associated
+ 		   nic_iface */
+-		nic_iface = nic->nic_iface;
++		nic_iface = current->nic_iface;
+ 		while (nic_iface != NULL) {
+ 			vlan_iface = nic_iface->vlan_next;
+ 			while (vlan_iface != NULL) {
+@@ -608,7 +644,7 @@ error:
+ }
+ 
+ /**
+- *  net_iface_init() - This function is used to add an interface to the 
++ *  nic_iface_init() - This function is used to add an interface to the
+  *                     structure cnic_uio
+  *  @return 0 on success, <0 on failure
+  */
+@@ -623,6 +659,8 @@ nic_interface_t *nic_iface_init()
+ 	memset(nic_iface, 0, sizeof(*nic_iface));
+ 	nic_iface->next = NULL;
+ 	nic_iface->vlan_next = NULL;
++	nic_iface->iface_num = IFACE_NUM_INVALID;
++	nic_iface->request_type = IP_CONFIG_OFF;
+ 
+ 	return nic_iface;
+ }
+@@ -630,112 +668,57 @@ nic_interface_t *nic_iface_init()
+ /**
+  *  nic_add_nic_iface() - This function is used to add an interface to the
+  *                        nic structure
++ *  Called with nic_mutex held
+  *  @param nic - struct nic device to add the interface to
+  *  @param nic_iface - network interface used to add to the nic
+  *  @return 0 on success, <0 on failure
+  */
+-int nic_add_nic_iface(nic_t * nic, nic_interface_t * nic_iface)
++int nic_add_nic_iface(nic_t *nic, nic_interface_t *nic_iface)
+ {
++	nic_interface_t *current, *prev;
++
++	/* Make sure it doesn't already exist */
++	current = nic_find_nic_iface(nic, nic_iface->protocol,
++				     nic_iface->vlan_id, nic_iface->iface_num,
++				     nic_iface->request_type);
++	if (current) {
++		LOG_DEBUG(PFX "%s: nic interface for VLAN: %d, protocol: %d"
++			  " already exist", nic->log_name, nic_iface->vlan_id,
++			  nic_iface->protocol);
++		return 0;
++	}
+ 
+-	pthread_mutex_lock(&nic->nic_mutex);
+-
+-	/*  Add the nic_interface */
+-	if (nic->nic_iface == NULL) {
+-		nic->nic_iface = nic_iface;
+-	} else {
+-		nic_interface_t *current = nic->nic_iface;
+-
+-		/*  Check to see if this interface already exists via 2
+-		 *  conditions: 1) VLAN 2) protocol */
+-		while (current != NULL) {
+-			if ((current->protocol == nic_iface->protocol) &&
+-			    (current->vlan_id == nic_iface->vlan_id)) {
+-				LOG_WARN(PFX "%s: nic interface alread exists"
+-					 "for VLAN: %d, protocol: %d",
+-					 nic->log_name, current->vlan_id,
+-					 current->protocol);
+-				goto error;
+-			}
+-			current = current->next;
+-		}
+-
+-		/*   This interface doesn't exists, we can safely add
+-		 *   this nic interface */
+-		current = nic->nic_iface;
+-		while (current->next != NULL) {
+-			current = current->next;
++	prev = NULL;
++	current = nic->nic_iface;
++	while (current != NULL) {
++		if (current->protocol == nic_iface->protocol) {
++			/* Replace parent */
++			nic_iface->vlan_next = current;
++			nic_iface->next = current->next;
++			current->next = NULL;
++			if (prev)
++				prev->next = nic_iface;
++			else
++				nic->nic_iface = nic_iface;
++			goto done;
+ 		}
+-
+-		current->next = nic_iface;
++		prev = current;
++		current = current->next;
+ 	}
+-
++	nic_iface->next = nic->nic_iface;
++	nic->nic_iface = nic_iface;
++done:
+ 	/* Set nic_interface common fields */
+ 	nic_iface->parent = nic;
++	memcpy(&nic_iface->ustack.uip_ethaddr.addr, nic->mac_addr, ETH_ALEN);
+ 	nic->num_of_nic_iface++;
+ 
+ 	LOG_INFO(PFX "%s: Added nic interface for VLAN: %d, protocol: %d",
+ 		 nic->log_name, nic_iface->vlan_id, nic_iface->protocol);
+ 
+-error:
+-	pthread_mutex_unlock(&nic->nic_mutex);
+-
+ 	return 0;
+ }
+ 
+-/**
+- *  nic_add_vlan_iface() - This function is used to add a vlan interface to the
+- *                         nic structure
+- *  @param nic - struct nic device to add the interface to
+- *  @param nic_iface - network interface to be added to
+- *  @param vlan_iface - vlan interface used to add to the nic_iface
+- *  @return 0 on success, <0 on failure
+- */
+-int nic_add_vlan_iface(nic_t *nic, nic_interface_t *nic_iface,
+-		       nic_interface_t *vlan_iface)
+-{
+-	pthread_mutex_lock(&nic->nic_mutex);
+-
+-	/*  Add the nic_interface */
+-	if (nic_iface == NULL)
+-		goto error;
+-	else {
+-		nic_interface_t *current = nic_iface->vlan_next;
+-
+-		/*  Check to see if this interface already exists via 2
+-		 *  conditions: 1) VLAN 2) protocol */
+-		while (current != NULL) {
+-			if ((current->protocol == vlan_iface->protocol) &&
+-			    (current->vlan_id == vlan_iface->vlan_id)) {
+-				LOG_WARN(PFX "%s: vlan interface already exists"
+-					 "for VLAN: %d, protocol: %d",
+-					 nic->log_name, current->vlan_id,
+-					 current->protocol);
+-				goto error;
+-			}
+-			current = current->vlan_next;
+-		}
+-
+-		/*   This interface doesn't exists, we can safely add
+-		 *   this nic interface */
+-		current = nic_iface;
+-		while (current->vlan_next != NULL)
+-			current = current->vlan_next;
+-
+-		current->vlan_next = vlan_iface;
+-	}
+-
+-	/* Set nic_interface common fields */
+-	vlan_iface->parent = nic;
+-	nic->num_of_nic_iface++;
+-
+-	LOG_INFO(PFX "%s: Added vlan interface for VLAN: %d, protocol: %d",
+-		 nic->log_name, vlan_iface->vlan_id, vlan_iface->protocol);
+-
+-error:
+-	pthread_mutex_unlock(&nic->nic_mutex);
+-
+-	return 0;
+-}
+ /******************************************************************************
+  * Routine to process interrupts from the NIC device
+  ******************************************************************************/
+@@ -752,13 +735,13 @@ int nic_process_intr(nic_t * nic, int discard_check)
+ 	struct timeval tv;
+ 
+ 	/*  Simple sanity checks */
+-	if ((discard_check != 1) && (nic->state & NIC_RUNNING) != NIC_RUNNING) {
++	if (discard_check != 1 && nic->state != NIC_RUNNING) {
+ 		LOG_ERR(PFX "%s: Couldn't process interupt NIC not running",
+ 			nic->log_name);
+ 		return -EBUSY;
+ 	}
+ 
+-	if ((discard_check != 1) && (nic->fd == INVALID_FD)) {
++	if (discard_check != 1 && nic->fd == INVALID_FD) {
+ 		LOG_ERR(PFX "%s: NIC fd not valid", nic->log_name);
+ 		return -EIO;
+ 	}
+@@ -767,11 +750,12 @@ int nic_process_intr(nic_t * nic, int discard_check)
+ 	FD_SET(nic->fd, &fdset);
+ 
+ 	tv.tv_sec = 0;
+-	if (nic->state & NIC_LONG_SLEEP) {
++	pthread_mutex_lock(&nic->nic_mutex);
++	if (nic->flags & NIC_LONG_SLEEP)
+ 		tv.tv_usec = 1000;
+-	} else {
++	else
+ 		tv.tv_usec = nic->rx_poll_usec;
+-	}
++	pthread_mutex_unlock(&nic->nic_mutex);
+ 
+ 	/*  Wait for an interrupt to come in or timeout */
+ 	ret = select(nic->fd + 1, &fdset, NULL, NULL, &tv);
+@@ -796,20 +780,20 @@ int nic_process_intr(nic_t * nic, int discard_check)
+ 	pthread_mutex_lock(&nic->nic_mutex);
+ 	if (ret > 0) {
+ 		nic->stats.interrupts++;
+-		LOG_DEBUG(PFX "%s: interrupt count: %d prev: %d",
+-			  nic->log_name, count, nic->intr_count);
++		LOG_PACKET(PFX "%s: interrupt count: %d prev: %d",
++			   nic->log_name, count, nic->intr_count);
+ 
+ 		if (count == nic->intr_count) {
+-			LOG_WARN(PFX "%s: got interrupt but count still the "
+-				 "same", nic->log_name, count);
++			LOG_PACKET(PFX "%s: got interrupt but count still the "
++				   "same", nic->log_name, count);
+ 		}
+ 
+ 		/*  Check if we missed an interrupt.  With UIO, 
+ 		 *  the count should be incremental */
+ 		if (count != nic->intr_count + 1) {
+ 			nic->stats.missed_interrupts++;
+-			LOG_DEBUG(PFX "%s: Missed interrupt! on %d not %d",
+-				  nic->log_name, count, nic->intr_count);
++			LOG_PACKET(PFX "%s: Missed interrupt! on %d not %d",
++				   nic->log_name, count, nic->intr_count);
+ 		}
+ 
+ 		nic->intr_count = count;
+@@ -833,9 +817,14 @@ static void prepare_ipv4_packet(nic_t * nic,
+ 	int queue_rc;
+ 	int vlan_id = 0;
+ 
+-	if (nic_iface->vlan_id && !(NIC_VLAN_STRIP_ENABLED & nic->flags))
+-		vlan_id = nic_iface->vlan_id;
+-
++	/* If the rx vlan tag is not stripped and vlan is present in the pkt,
++	   manual stripping is required because tx is using hw vlan tag! */
++	if (pkt->network_layer == pkt->data_link_layer +
++				  sizeof(struct uip_vlan_eth_hdr)) {
++		/* VLAN is detected in the pkt buf */
++		memcpy(pkt->data_link_layer + 12, pkt->network_layer - 2,
++		       pkt->buf_size - sizeof(struct uip_vlan_eth_hdr) + 2);
++	}
+ 	dest_ipv4_addr = uip_determine_dest_ipv4_addr(ustack, ipaddr);
+ 	if (dest_ipv4_addr == LOCAL_BROADCAST) {
+ 		uip_build_eth_header(ustack, ipaddr, NULL, pkt, vlan_id);
+@@ -867,9 +856,12 @@ static void prepare_ipv6_packet(nic_t * nic,
+ 	struct uip_vlan_eth_hdr *eth_vlan;
+ 	int vlan_id = 0;
+ 
+-	if (nic_iface->vlan_id && !(NIC_VLAN_STRIP_ENABLED & nic->flags))
+-		vlan_id = nic_iface->vlan_id;
+-
++	if (pkt->network_layer == pkt->data_link_layer +
++				  sizeof(struct uip_vlan_eth_hdr)) {
++		/* VLAN is detected in the pkt buf */
++		memcpy(pkt->data_link_layer + 12, pkt->network_layer - 2,
++		       pkt->buf_size - sizeof(struct uip_vlan_eth_hdr) + 2);
++	}
+ 	eth = (struct uip_eth_hdr *)ustack->data_link_layer;
+ 	eth_vlan = (struct uip_vlan_eth_hdr *)ustack->data_link_layer;
+ 	if (vlan_id == 0) {
+@@ -897,96 +889,96 @@ static void prepare_ustack(nic_t * nic,
+ 	 *  there is a VLAN tag or not, or if the hardware 
+ 	 *  has stripped out the
+ 	 *  VLAN tag */
+-	if ((nic_iface->vlan_id == 0) || (NIC_VLAN_STRIP_ENABLED & nic->flags)) {
+-		ustack->network_layer = ustack->data_link_layer +
+-		    sizeof(struct uip_eth_hdr);
+-	} else {
+-		ustack->network_layer = ustack->data_link_layer +
+-		    sizeof(struct uip_vlan_eth_hdr);
+-	}
++	ustack->network_layer = ustack->data_link_layer +
++				sizeof(struct uip_eth_hdr);
+ 	/* Init buffer to be IPv6 */
+ 	if (nic_iface->ustack.ip_config == IPV6_CONFIG_DHCP ||
+ 	    nic_iface->ustack.ip_config == IPV6_CONFIG_STATIC) {
+ 		eth = (struct ether_header *)ustack->data_link_layer;
+-		eth->ether_type = UIP_ETHTYPE_IPv6;
++		eth->ether_type = htons(UIP_ETHTYPE_IPv6);
+ 	}
+ }
+ 
+-static int check_timers(nic_t * nic,
+-			struct timer *periodic_timer, struct timer *arp_timer)
++int do_timers_per_nic_iface(nic_t *nic, nic_interface_t *nic_iface,
++			    struct timer *arp_timer)
+ {
+-	if (timer_expired(periodic_timer)) {
+-		int i;
+-		nic_interface_t *current;
+-
+-		timer_reset(periodic_timer);
++	packet_t *pkt;
++	struct uip_stack *ustack = &nic_iface->ustack;
++	int i;
+ 
+-		pthread_mutex_lock(&nic->nic_mutex);
++	pkt = get_next_free_packet(nic);
++	if (pkt == NULL)
++		return -EIO;
+ 
+-		current = nic->nic_iface;
+-		while (current != NULL) {
+-			packet_t *pkt;
+-			struct uip_stack *ustack = &current->ustack;
++	if (nic_iface->ustack.ip_config == AF_INET) {
++		for (i = 0; i < UIP_UDP_CONNS; i++) {
++			prepare_ustack(nic, nic_iface, ustack, pkt);
+ 
+-			pkt = get_next_free_packet(nic);
+-			if (pkt == NULL) {
+-				current = current->next;
+-				continue;
++			uip_udp_periodic(ustack, i);
++			/* If the above function invocation resulted
++			 * in data that should be sent out on the
++			 * network, the global variable uip_len is
++			 * set to a value > 0. */
++			if (ustack->uip_len > 0) {
++				pkt->buf_size = ustack->uip_len;
++				prepare_ipv4_packet(nic, nic_iface, ustack,
++						    pkt);
++				(*nic->ops->write) (nic, nic_iface, pkt);
++				ustack->uip_len = 0;
+ 			}
+-
+-			for (i = 0; i < UIP_UDP_CONNS; i++) {
+-				prepare_ustack(nic, current, ustack, pkt);
+-
+-				uip_udp_periodic(ustack, i);
+-				/* If the above function invocation resulted
+-				 * in data that should be sent out on the 
+-				 * network, the global variable uip_len is 
+-				 * set to a value > 0. */
+-				if (ustack->uip_len > 0) {
+-					pkt->buf_size = ustack->uip_len;
+-
+-					prepare_ipv4_packet(nic,
+-							    current,
+-							    ustack, pkt);
+-
+-					(*nic->ops->write) (nic, current, pkt);
+-					ustack->uip_len = 0;
+-				}
++		}
++	} else {
++		/* Added periodic poll for IPv6 NDP engine */
++		if (ustack->ndpc != NULL) {	/* If engine is active */
++			prepare_ustack(nic, nic_iface, ustack, pkt);
++
++			uip_ndp_periodic(ustack);
++			/* If the above function invocation resulted
++			 * in data that should be sent out on the
++			 * network, the global variable uip_len is
++			 * set to a value > 0. */
++			if (ustack->uip_len > 0) {
++				pkt->buf_size = ustack->uip_len;
++				prepare_ipv6_packet(nic, nic_iface, ustack,
++						    pkt);
++				(*nic->ops->write) (nic, nic_iface, pkt);
++				ustack->uip_len = 0;
+ 			}
++		}
++	}
++	/* Call the ARP timer function every 10 seconds. */
++	if (timer_expired(arp_timer)) {
++		timer_reset(arp_timer);
++		uip_arp_timer();
++	}
++	put_packet_in_free_queue(pkt, nic);
++	return 0;
++}
+ 
+-			/* Added periodic poll for IPv6 NDP engine */
+-			if (ustack->ndpc != NULL) {	/* If engine is active */
+-				prepare_ustack(nic, current, ustack, pkt);
+-
+-				uip_ndp_periodic(ustack);
+-				/* If the above function invocation resulted
+-				 * in data that should be sent out on the 
+-				 * network, the global variable uip_len is 
+-				 * set to a value > 0. */
+-				if (ustack->uip_len > 0) {
+-					pkt->buf_size = ustack->uip_len;
+-					prepare_ipv6_packet(nic,
+-							    current,
+-							    ustack, pkt);
+-					(*nic->ops->write) (nic, current, pkt);
+-					ustack->uip_len = 0;
+-				}
+-			}
++static int check_timers(nic_t *nic,
++			struct timer *periodic_timer, struct timer *arp_timer)
++{
++	if (timer_expired(periodic_timer)) {
++		nic_interface_t *nic_iface, *vlan_iface;
+ 
+-			/* Call the ARP timer function every 10 seconds. */
+-			if (timer_expired(arp_timer)) {
+-				timer_reset(arp_timer);
+-				uip_arp_timer();
+-			}
++		timer_reset(periodic_timer);
+ 
+-			put_packet_in_free_queue(pkt, nic);
++		pthread_mutex_lock(&nic->nic_mutex);
+ 
+-			current = current->next;
++		nic_iface = nic->nic_iface;
++		while (nic_iface != NULL) {
++			do_timers_per_nic_iface(nic, nic_iface, arp_timer);
++			vlan_iface = nic_iface->vlan_next;
++			while (vlan_iface != NULL) {
++				do_timers_per_nic_iface(nic, vlan_iface,
++							arp_timer);
++				vlan_iface = vlan_iface->vlan_next;
++			}
++			nic_iface = nic_iface->next;
+ 		}
+ 
+ 		pthread_mutex_unlock(&nic->nic_mutex);
+ 	}
+-
+ 	return 0;
+ }
+ 
+@@ -1012,109 +1004,71 @@ int process_packets(nic_t * nic,
+ 		uint16_t type = 0;
+ 		int af_type = 0;
+ 		struct uip_stack *ustack;
+-		nic_interface_t *vlan_iface;
++		struct ip_hdr *ip;
++		pIPV6_HDR ip6;
++		void *dst_ip;
++		uint16_t vlan_id;
+ 
+-		if ((pkt->vlan_tag == 0) ||
++		pkt->data_link_layer = pkt->buf;
++
++		vlan_id = pkt->vlan_tag & 0xFFF;
++		if ((vlan_id == 0) ||
+ 		    (NIC_VLAN_STRIP_ENABLED & nic->flags)) {
+ 			type = ntohs(ETH_BUF(pkt->buf)->type);
++			pkt->network_layer = pkt->data_link_layer +
++					     sizeof(struct uip_eth_hdr);
+ 		} else {
+ 			type = ntohs(VLAN_ETH_BUF(pkt->buf)->type);
++			pkt->network_layer = pkt->data_link_layer +
++					     sizeof(struct uip_vlan_eth_hdr);
+ 		}
+ 
+ 		switch (type) {
+ 		case UIP_ETHTYPE_IPv6:
+ 			af_type = AF_INET6;
++			ip6 = (pIPV6_HDR) pkt->network_layer;
++			dst_ip = (void *)&ip6->ipv6_dst;
+ 			break;
+ 		case UIP_ETHTYPE_IPv4:
+-			af_type = AF_INET;
+-			break;
+ 		case UIP_ETHTYPE_ARP:
+ 			af_type = AF_INET;
++			ip = (struct ip_hdr *) pkt->network_layer;
++			dst_ip = (void *)&ip->destipaddr;
+ 			break;
+ 		default:
+-			LOG_DEBUG(PFX "%s: Ignoring vlan:0x%x ethertype:0x%x",
+-				  nic->log_name, pkt->vlan_tag, type);
++			LOG_PACKET(PFX "%s: Ignoring vlan:0x%x ethertype:0x%x",
++				   nic->log_name, vlan_id, type);
+ 			goto done;
+ 		}
+ 
+-		/*  check if we have the given VLAN interface */
+-		if (nic_iface == NULL) {
+-			nic_iface = nic_find_nic_iface_protocol(nic, 0,
+-								af_type);
+-			if (nic_iface == NULL) {
+-				LOG_INFO(PFX "%s: Couldn't find interface for "
+-					 "VLAN: %d af_type %d creating it",
+-					 nic->log_name, pkt->vlan_tag, af_type);
+-
+-				/*  Create the vlan interface */
+-				nic_iface = nic_iface_init();
+-
+-				if (nic_iface == NULL) {
+-					LOG_WARN(PFX "%s: Couldn't "
+-						 "allocate "
+-						 "nic_iface for "
+-						 "VLAN: %d af_type %d",
+-						 nic->log_name, pkt->vlan_tag,
+-						 af_type);
+-					rc = 0;
+-					goto done;
+-				}
+-
+-				nic_iface->protocol = af_type;
+-				nic_iface->vlan_id = 0;
+-				nic_add_nic_iface(nic, nic_iface);
++		pthread_mutex_lock(&nic->nic_mutex);
+ 
+-				persist_all_nic_iface(nic);
+-			}
+-			if (pkt->vlan_tag) {
+-				vlan_iface = nic_find_vlan_iface_protocol(nic,
+-						nic_iface, pkt->vlan_tag,
+-						af_type);
+-				if (vlan_iface == NULL) {
+-					LOG_INFO(PFX "%s couldn't find "
+-						 "interface with VLAN ="
+-						 " %d ip_type: 0x%x "
+-						 "creating it",
+-						 nic->log_name, pkt->vlan_tag,
+-						 af_type);
+-
+-					/*  Create the nic interface */
+-					vlan_iface = nic_iface_init();
+-
+-					if (vlan_iface == NULL) {
+-						LOG_ERR(PFX "Couldn't allocate "
+-							"nic_iface for VLAN: %d",
+-							vlan_iface,
+-							pkt->vlan_tag);
+-						rc = 0;
+-						goto done;
+-					}
+-					vlan_iface->protocol = af_type;
+-					vlan_iface->vlan_id = pkt->vlan_tag;
+-					nic_add_vlan_iface(nic, nic_iface,
+-							   vlan_iface);
+-					/* TODO: When VLAN support is placed */
+-					/* in the iface file revisit this */
+-					/* code */
+-					memcpy(vlan_iface->ustack.hostaddr,
+-					       nic_iface->ustack.hostaddr,
+-					    sizeof(nic_iface->ustack.hostaddr));
+-					memcpy(vlan_iface->ustack.netmask,
+-					       nic_iface->ustack.netmask,
+-					     sizeof(nic_iface->ustack.netmask));
+-					memcpy(vlan_iface->ustack.netmask6,
+-					       nic_iface->ustack.netmask6,
+-					    sizeof(nic_iface->ustack.netmask6));
+-					memcpy(vlan_iface->ustack.hostaddr6,
+-					       nic_iface->ustack.hostaddr6,
+-					   sizeof(nic_iface->ustack.hostaddr6));
+-
+-					persist_all_nic_iface(nic);
+-				}
+-				nic_iface = vlan_iface;
++		/*  check if we have the given VLAN interface */
++		if (nic_iface != NULL) {
++			if (vlan_id != nic_iface->vlan_id) {
++				/* Matching nic_iface not found, drop */
++				pthread_mutex_unlock(&nic->nic_mutex);
++				rc = EINVAL;  /* Return the +error code */
++				goto done;
+ 			}
++			goto nic_iface_present;
+ 		}
+ 
++		/* Best effort to find the correct instance
++		   Input: protocol and vlan_tag */
++		nic_iface = nic_find_nic_iface(nic, af_type, vlan_id,
++					       IFACE_NUM_INVALID,
++					       IP_CONFIG_OFF);
++		if (nic_iface == NULL) {
++			/* Matching nic_iface not found */
++			pthread_mutex_unlock(&nic->nic_mutex);
++			LOG_PACKET(PFX "%s: Couldn't find interface for "
++				   "VLAN: %d af_type %d",
++				nic->log_name, vlan_id, af_type);
++			rc = EINVAL;  /* Return the +error code */
++			goto done;
++		}
++nic_iface_present:
+ 		pkt->nic_iface = nic_iface;
+ 
+ 		ustack = &nic_iface->ustack;
+@@ -1123,27 +1077,17 @@ int process_packets(nic_t * nic,
+ 		ustack->uip_len = pkt->buf_size;
+ 		ustack->data_link_layer = pkt->buf;
+ 
+-		pkt->data_link_layer = pkt->buf;
+-
+ 		/*  Adjust the network layer pointer depending if there is a
+ 		 *  VLAN tag or not, or if the hardware has stripped out the
+ 		 *  VLAN tag */
+-		if ((pkt->vlan_tag == 0) ||
+-		    (NIC_VLAN_STRIP_ENABLED & nic->flags)) {
++		if ((vlan_id == 0) ||
++		    (NIC_VLAN_STRIP_ENABLED & nic->flags))
+ 			ustack->network_layer = ustack->data_link_layer +
+ 			    sizeof(struct uip_eth_hdr);
+-			pkt->network_layer = pkt->data_link_layer +
+-			    sizeof(struct uip_eth_hdr);
+-			type = ntohs(ETH_BUF(pkt->buf)->type);
+-		} else {
++		else
+ 			ustack->network_layer = ustack->data_link_layer +
+ 			    sizeof(struct uip_vlan_eth_hdr);
+-			pkt->network_layer = pkt->data_link_layer +
+-			    sizeof(struct uip_vlan_eth_hdr);
+-			type = ntohs(VLAN_ETH_BUF(pkt->buf)->type);
+-		}
+ 
+-		pthread_mutex_lock(&nic->nic_mutex);
+ 		/*  determine how we should process this packet based on the
+ 		 *  ethernet type */
+ 		switch (type) {
+@@ -1270,25 +1214,174 @@ static int process_dhcp_loop(nic_t * nic,
+ 		}
+ 
+ 		if (timercmp(&total_time, &current_time, <)) {
+-			LOG_ERR(PFX "%s: timeout waiting for DHCP",
++			LOG_ERR(PFX "%s: timeout waiting for DHCP/NDP",
+ 				nic->log_name);
++			if (nic_iface->ustack.ip_config == IPV6_CONFIG_DHCP ||
++			    nic_iface->ustack.ip_config == IPV6_CONFIG_STATIC)
++				n->retry_count = IPV6_MAX_ROUTER_SOL_RETRY;
+ 			return -EIO;
+ 		}
+ 	}
+ 
+ 	if (nic->flags & NIC_GOING_DOWN)
+ 		return -EIO;
++	else if (nic->flags & NIC_DISABLED)
++		return -EINVAL;
+ 	else
+ 		return 0;
+ }
+ 
++/* Called with nic_mutex locked */
++static int do_acquisition(nic_t *nic, nic_interface_t *nic_iface,
++			  struct timer *periodic_timer, struct timer *arp_timer)
++{
++	struct in_addr addr;
++	struct in6_addr addr6;
++	void *res;
++	char buf[INET6_ADDRSTRLEN];
++	int rc = -1;
++
++	/* New acquisition */
++	uip_init(&nic_iface->ustack, nic->flags & NIC_IPv6_ENABLED);
++	memcpy(&nic_iface->ustack.uip_ethaddr.addr, nic->mac_addr, ETH_ALEN);
++
++	LOG_INFO(PFX "%s: Initialized ip stack: VLAN: %d",
++		 nic->log_name, nic_iface->vlan_id);
++
++	LOG_INFO(PFX "%s: mac: %02x:%02x:%02x:%02x:%02x:%02x",
++		 nic->log_name,
++		 nic_iface->mac_addr[0],
++		 nic_iface->mac_addr[1],
++		 nic_iface->mac_addr[2],
++		 nic_iface->mac_addr[3],
++		 nic_iface->mac_addr[4],
++		 nic_iface->mac_addr[5]);
++
++	switch (nic_iface->ustack.ip_config) {
++	case IPV4_CONFIG_STATIC:
++		memcpy(&addr.s_addr, nic_iface->ustack.hostaddr,
++		       sizeof(addr.s_addr));
++
++		LOG_INFO(PFX "%s: Using IP address: %s",
++			 nic->log_name, inet_ntoa(addr));
++
++		memcpy(&addr.s_addr, nic_iface->ustack.netmask,
++		       sizeof(addr.s_addr));
++
++		LOG_INFO(PFX "%s: Using netmask: %s",
++			 nic->log_name, inet_ntoa(addr));
++
++		set_uip_stack(&nic_iface->ustack,
++			      &nic_iface->ustack.hostaddr,
++			      &nic_iface->ustack.netmask,
++			      &nic_iface->ustack.default_route_addr,
++			      nic_iface->mac_addr);
++		break;
++
++	case IPV4_CONFIG_DHCP:
++		set_uip_stack(&nic_iface->ustack,
++			      &nic_iface->ustack.hostaddr,
++			      &nic_iface->ustack.netmask,
++			      &nic_iface->ustack.default_route_addr,
++			      nic_iface->mac_addr);
++		if (dhcpc_init(nic, &nic_iface->ustack,
++			       nic_iface->mac_addr, ETH_ALEN)) {
++			if (nic_iface->ustack.dhcpc) {
++				LOG_DEBUG(PFX "%s: DHCPv4 engine already "
++					  "initialized!", nic->log_name);
++				goto skip;
++			} else {
++				LOG_DEBUG(PFX "%s: DHCPv4 engine failed "
++					  "initialization!", nic->log_name);
++				goto error;
++			}
++		}
++		pthread_mutex_unlock(&nic->nic_mutex);
++		rc = process_dhcp_loop(nic, nic_iface, periodic_timer,
++				       arp_timer);
++		pthread_mutex_lock(&nic->nic_mutex);
++
++		if (rc) {
++			LOG_ERR(PFX "%s: DHCP failed", nic->log_name);
++			/* For DHCPv4 failure, the ustack must be cleaned so
++			   it can re-acquire on the next iscsid request */
++			uip_reset(&nic_iface->ustack);
++
++			/*  Signal that the device enable is
++			    done */
++			pthread_cond_broadcast(&nic->enable_done_cond);
++			pthread_mutex_unlock(&nic->nic_mutex);
++
++			if (nic->enable_thread == INVALID_THREAD)
++				goto dhcp_err;
++
++			rc = pthread_join(nic->enable_thread, &res);
++			if (rc != 0)
++				LOG_ERR(PFX "%s: Couldn't join to canceled "
++					"enable nic thread", nic->log_name);
++dhcp_err:
++			pthread_mutex_lock(&nic->nic_mutex);
++			goto error;
++		}
++
++		if (nic->flags & NIC_DISABLED) {
++			/* Break out of this loop */
++			break;
++		}
++
++		LOG_INFO(PFX "%s: Initialized dhcp client", nic->log_name);
++		break;
++
++	case IPV6_CONFIG_DHCP:
++	case IPV6_CONFIG_STATIC:
++		if (ndpc_init(nic, &nic_iface->ustack, nic_iface->mac_addr,
++			      ETH_ALEN)) {
++			LOG_DEBUG(PFX "%s: IPv6 engine already initialized!",
++				  nic->log_name);
++			goto skip;
++		}
++		pthread_mutex_unlock(&nic->nic_mutex);
++		rc = process_dhcp_loop(nic, nic_iface, periodic_timer,
++				       arp_timer);
++		pthread_mutex_lock(&nic->nic_mutex);
++		if (rc) {
++			/* Don't reset and allow to use RA and LL */
++			LOG_ERR(PFX "%s: IPv6 DHCP/NDP failed", nic->log_name);
++		}
++		if (nic_iface->ustack.ip_config == IPV6_CONFIG_STATIC) {
++			memcpy(&addr6.s6_addr, nic_iface->ustack.hostaddr6,
++			       sizeof(addr6.s6_addr));
++			inet_ntop(AF_INET6, addr6.s6_addr, buf, sizeof(buf));
++			LOG_INFO(PFX "%s: hostaddr IP: %s", nic->log_name, buf);
++			memcpy(&addr6.s6_addr, nic_iface->ustack.netmask6,
++			       sizeof(addr6.s6_addr));
++			inet_ntop(AF_INET6, addr6.s6_addr, buf, sizeof(buf));
++			LOG_INFO(PFX "%s: netmask IP: %s", nic->log_name, buf);
++		}
++		break;
++
++	default:
++		LOG_INFO(PFX "%s: ipconfig = %d?", nic->log_name,
++			 nic_iface->ustack.ip_config);
++	}
++skip:
++	/* Mark acquisition done for this nic iface */
++	nic_iface->flags &= ~NIC_IFACE_ACQUIRE;
++
++	LOG_INFO(PFX "%s: enabled vlan %d protocol: %d", nic->log_name,
++		 nic_iface->vlan_id, nic_iface->protocol);
++	return 0;
++
++error:
++	return -EIO;
++}
++
+ void *nic_loop(void *arg)
+ {
+ 	nic_t *nic = (nic_t *) arg;
+ 	int rc = -1;
+-	struct timer periodic_timer, arp_timer;
+ 	sigset_t set;
+-	void *res;
++	struct timer periodic_timer, arp_timer;
+ 
+ 	sigfillset(&set);
+ 	rc = pthread_sigmask(SIG_BLOCK, &set, NULL);
+@@ -1302,10 +1395,11 @@ void *nic_loop(void *arg)
+ 	pthread_mutex_lock(&nic->nic_mutex);
+ 	pthread_cond_signal(&nic->nic_loop_started_cond);
+ 
++	/* nic_mutex must be locked */
+ 	while ((event_loop_stop == 0) &&
+ 	       !(nic->flags & NIC_EXIT_MAIN_LOOP) &&
+ 	       !(nic->flags & NIC_GOING_DOWN)) {
+-		nic_interface_t *nic_iface;
++		nic_interface_t *nic_iface, *vlan_iface;
+ 
+ 		if (nic->flags & NIC_DISABLED) {
+ 			LOG_DEBUG(PFX "%s: Waiting to be enabled",
+@@ -1322,8 +1416,6 @@ void *nic_loop(void *arg)
+ 			}
+ 			LOG_DEBUG(PFX "%s: is now enabled", nic->log_name);
+ 		}
+-		pthread_mutex_unlock(&nic->nic_mutex);
+-
+ 		/*  initialize the device to send/rec data */
+ 		rc = (*nic->ops->open) (nic);
+ 		if (rc != 0) {
+@@ -1331,18 +1423,17 @@ void *nic_loop(void *arg)
+ 				nic->log_name);
+ 
+ 			if (rc == -ENOTSUP)
+-				nic->flags &= NIC_EXIT_MAIN_LOOP;
++				nic->flags |= NIC_EXIT_MAIN_LOOP;
+ 			else
+ 				nic->flags &= ~NIC_ENABLED;
+ 
+ 			/* Signal that the device enable is done */
+ 			pthread_cond_broadcast(&nic->enable_done_cond);
+ 			pthread_mutex_unlock(&nic->nic_mutex);
+-
+ 			goto dev_close;
+ 		}
+-
+ 		nic_set_all_nic_iface_mac_to_parent(nic);
++		pthread_mutex_unlock(&nic->nic_mutex);
+ 
+ 		rc = alloc_free_queue(nic, 5);
+ 		if (rc != 5) {
+@@ -1354,13 +1445,12 @@ void *nic_loop(void *arg)
+ 					"instead of %d", nic->log_name, 5);
+ 				/* Signal that the device enable is done */
+ 				pthread_cond_broadcast(&nic->enable_done_cond);
+-				pthread_mutex_unlock(&nic->nic_mutex);
+ 				goto dev_close;
+ 			}
+ 		}
+ 		/* Indication for the nic_disable routine that the nic
+ 		   has started running */
+-		nic->state |= NIC_STARTED_RUNNING;
++		nic->state = NIC_STARTED_RUNNING;
+ 
+ 		/*  Initialize the system clocks */
+ 		timer_set(&periodic_timer, CLOCK_SECOND / 2);
+@@ -1369,192 +1459,25 @@ void *nic_loop(void *arg)
+ 		/*  Prepare the stack for each of the VLAN interfaces */
+ 		pthread_mutex_lock(&nic->nic_mutex);
+ 
++		/* If DHCP fails, exit loop and restart the engine */
+ 		nic_iface = nic->nic_iface;
+ 		while (nic_iface != NULL) {
+-			uip_init(&nic_iface->ustack,
+-				 nic->flags & NIC_IPv6_ENABLED);
+-			memcpy(&nic_iface->ustack.uip_ethaddr.addr,
+-			       nic->mac_addr, 6);
+-
+-			LOG_INFO(PFX "%s: Initialized ip stack: VLAN: %d",
+-				 nic->log_name, nic_iface->vlan_id);
+-
+-			LOG_INFO(PFX "%s: mac: %02x:%02x:%02x:%02x:%02x:%02x",
+-				 nic->log_name,
+-				 nic_iface->mac_addr[0],
+-				 nic_iface->mac_addr[1],
+-				 nic_iface->mac_addr[2],
+-				 nic_iface->mac_addr[3],
+-				 nic_iface->mac_addr[4],
+-				 nic_iface->mac_addr[5]);
+-
+-			if (nic_iface->ustack.ip_config == IPV4_CONFIG_STATIC) {
+-				struct in_addr addr;
+-				uip_ip4addr_t tmp = { 0, 0 };
+-
+-				memcpy(&addr.s_addr, nic_iface->ustack.hostaddr,
+-				       sizeof(addr.s_addr));
+-
+-				LOG_INFO(PFX "%s: Using IP address: %s",
+-					 nic->log_name, inet_ntoa(addr));
+-
+-				memcpy(&addr.s_addr, nic_iface->ustack.netmask,
+-				       sizeof(addr.s_addr));
+-
+-				LOG_INFO(PFX "%s: Using netmask: %s",
+-					 nic->log_name, inet_ntoa(addr));
+-
+-				set_uip_stack(&nic_iface->ustack,
+-					      &nic_iface->ustack.hostaddr,
+-					      &nic_iface->ustack.netmask,
+-					      &tmp, nic_iface->mac_addr);
+-
+-			} else if (nic_iface->ustack.ip_config ==
+-				   IPV4_CONFIG_DHCP) {
+-				struct uip_stack *ustack = &nic_iface->ustack;
+-				uip_ip4addr_t tmp = { 0, 0 };
+-
+-				set_uip_stack(&nic_iface->ustack,
+-					      &nic_iface->ustack.hostaddr,
+-					      &nic_iface->ustack.netmask,
+-					      &tmp, nic_iface->mac_addr);
+-				if (dhcpc_init(nic, ustack,
+-					       nic_iface->mac_addr, ETH_ALEN)) {
+-					if (ustack->dhcpc) {
+-						LOG_DEBUG(PFX "%s: DHCPv4 "
+-							  "engine already "
+-							  "initialized!",
+-							  nic->log_name);
+-						goto skip;
+-					} else {
+-						LOG_DEBUG(PFX "%s: DHCPv4 "
+-							  "engine failed "
+-							  "initialization!",
+-							  nic->log_name);
+-						goto dev_close_free;
+-					}
+-				}
+-				pthread_mutex_unlock(&nic->nic_mutex);
+-				rc = process_dhcp_loop(nic, nic_iface,
++			if (nic_iface->flags & NIC_IFACE_ACQUIRE) {
++				do_acquisition(nic, nic_iface,
++					       &periodic_timer,
++					       &arp_timer);
++			}
++			vlan_iface = nic_iface->vlan_next;
++			while (vlan_iface != NULL) {
++				if (vlan_iface->flags & NIC_IFACE_ACQUIRE) {
++					do_acquisition(nic, vlan_iface,
+ 						       &periodic_timer,
+ 						       &arp_timer);
+-				pthread_mutex_lock(&nic->nic_mutex);
+-
+-				if (rc) {
+-					LOG_ERR(PFX "%s: DHCP failed",
+-						nic->log_name);
+-					nic->flags |= NIC_DISABLED |
+-					    NIC_RESET_UIP;
+-					nic->flags &= ~NIC_ENABLED;
+-					/*  Signal that the device enable is
+-					    done */
+-					pthread_cond_broadcast(
+-							&nic->enable_done_cond);
+-
+-					pthread_mutex_unlock(&nic->nic_mutex);
+-
+-					if (nic->enable_thread ==
+-					    INVALID_THREAD)
+-						goto dev_close_free;
+-
+-					rc = pthread_join(nic->enable_thread,
+-							  &res);
+-					if (rc != 0)
+-						LOG_ERR(PFX "%s: Couldn't join "
+-							"to canceled enable nic"
+-							" thread",
+-							nic->log_name);
+-
+-					goto dev_close_free;
+ 				}
+-
+-				if (nic->flags & NIC_DISABLED) {
+-					pthread_mutex_unlock(&nic->nic_mutex);
+-					break;
+-				}
+-
+-				LOG_INFO(PFX "%s: Initialized dhcp client",
+-					 nic->log_name);
+-			} else if (nic_iface->ustack.ip_config ==
+-				   IPV6_CONFIG_DHCP ||
+-				   nic_iface->ustack.ip_config ==
+-				   IPV6_CONFIG_STATIC) {
+-				struct in6_addr addr6;
+-				char buf[INET6_ADDRSTRLEN];
+-
+-				/* Do router solicitation for both STATIC and
+-				   DHCP - all NDP handling will take place in
+-				   the DHCP loop
+-				   STATIC - router advertisement will be handled
+-				   in the uip background loop
+-				 */
+-				if (ndpc_init(nic, &nic_iface->ustack,
+-					      nic_iface->mac_addr, ETH_ALEN)) {
+-					LOG_DEBUG(PFX "%s: IPv6 engine already"
+-						  "initialized!",
+-						  nic->log_name);
+-					goto skip;
+-				}
+-				if (nic_iface->ustack.ip_config ==
+-				    IPV6_CONFIG_DHCP) {
+-					pthread_mutex_unlock(&nic->nic_mutex);
+-					rc = process_dhcp_loop(nic, nic_iface,
+-							       &periodic_timer,
+-							       &arp_timer);
+-					pthread_mutex_lock(&nic->nic_mutex);
+-					if (rc) {
+-						/* Don't reset and allow to
+-						   use RA and LL */
+-						LOG_ERR(PFX "%s: DHCPv6 failed",
+-							nic->log_name);
+-					}
+-					if (nic->flags & NIC_DISABLED) {
+-						pthread_mutex_unlock(&nic->
+-								     nic_mutex);
+-						break;
+-					}
+-				} else {
+-					pthread_mutex_unlock(&nic->nic_mutex);
+-					rc = process_dhcp_loop(nic, nic_iface,
+-							       &periodic_timer,
+-							       &arp_timer);
+-					pthread_mutex_lock(&nic->nic_mutex);
+-					if (rc) {
+-						LOG_ERR(PFX "%s: IPv6 rtr "
+-							"failed",
+-							nic->log_name);
+-					}
+-					memcpy(&addr6.s6_addr,
+-					       nic_iface->ustack.hostaddr6,
+-					       sizeof(addr6.s6_addr));
+-					inet_ntop(AF_INET6,
+-						  addr6.s6_addr,
+-						  buf, sizeof(buf));
+-					LOG_INFO(PFX "%s: hostaddr IP: %s",
+-						 nic->log_name, buf);
+-
+-					memcpy(&addr6.s6_addr,
+-					       nic_iface->ustack.netmask6,
+-					       sizeof(addr6.s6_addr));
+-					inet_ntop(AF_INET6,
+-						  addr6.s6_addr,
+-						  buf, sizeof(buf));
+-					LOG_INFO(PFX "%s: netmask IP: %s",
+-						 nic->log_name, buf);
+-				}
+-			} else {
+-				LOG_INFO(PFX "%s: ipconfig = %d?",
+-					 nic->log_name,
+-					 nic_iface->ustack.ip_config);
++				vlan_iface = vlan_iface->next;
+ 			}
+-skip:
+-			LOG_INFO(PFX "%s: enabled vlan %d protocol: %d",
+-				 nic->log_name,
+-				 nic_iface->vlan_id, nic_iface->protocol);
+-
+-			nic_iface = nic_iface->vlan_next;
++			nic_iface = nic_iface->next;
+ 		}
+-
+ 		if (nic->flags & NIC_DISABLED) {
+ 			LOG_WARN(PFX "%s: nic was disabled during nic loop, "
+ 				 "closing flag 0x%x",
+@@ -1567,10 +1490,7 @@ skip:
+ 
+ 		/*  This is when we start the processing of packets */
+ 		nic->start_time = time(NULL);
+-		nic->flags &= ~NIC_UNITIALIZED;
+-		nic->flags |= NIC_INITIALIZED;
+-		nic->state &= ~NIC_STOPPED;
+-		nic->state |= NIC_RUNNING;
++		nic->state = NIC_RUNNING;
+ 
+ 		nic->flags &= ~NIC_ENABLED_PENDING;
+ 
+@@ -1580,14 +1500,14 @@ skip:
+ 
+ 		LOG_INFO(PFX "%s: entering main nic loop", nic->log_name);
+ 
+-		while ((nic->state & NIC_RUNNING) &&
++		while ((nic->state == NIC_RUNNING) &&
+ 		       (event_loop_stop == 0) &&
+ 		       !(nic->flags & NIC_GOING_DOWN)) {
+ 			/*  Check the periodic and ARP timer */
+ 			check_timers(nic, &periodic_timer, &arp_timer);
+ 			rc = nic_process_intr(nic, 0);
+ 			while ((rc > 0) &&
+-			       (nic->state & NIC_RUNNING) &&
++			       (nic->state == NIC_RUNNING) &&
+ 			       !(nic->flags & NIC_GOING_DOWN)) {
+ 				rc = process_packets(nic,
+ 						     &periodic_timer,
+@@ -1609,33 +1529,7 @@ dev_close:
+ 		} else {
+ 			pthread_mutex_destroy(&nic->xmit_mutex);
+ 			pthread_mutex_init(&nic->xmit_mutex, NULL);
+-
+-			if (nic->flags & NIC_RESET_UIP) {
+-				nic_interface_t *nic_iface = nic->nic_iface;
+-				nic_interface_t *vlan_iface;
+-				while (nic_iface != NULL) {
+-					LOG_INFO(PFX "%s: resetting uIP stack",
+-						 nic->log_name);
+-					uip_reset(&nic_iface->ustack);
+-					vlan_iface = nic_iface->vlan_next;
+-					while (vlan_iface != NULL) {
+-						LOG_INFO(PFX "%s: resetting "
+-							 "vlan uIP stack",
+-							 nic->log_name);
+-						uip_reset(&vlan_iface->ustack);
+-						vlan_iface =
+-							vlan_iface->vlan_next;
+-					}
+-					nic_iface = nic_iface->next;
+-				}
+-				nic->flags &= ~NIC_RESET_UIP;
+-			}
+ 		}
+-
+-		nic->flags |= NIC_UNITIALIZED;
+-		nic->flags &= ~NIC_INITIALIZED;
+-		nic->flags &= ~NIC_ENABLED_PENDING;
+-
+ 		nic->pending_count = 0;
+ 
+ 		if (!(nic->flags & NIC_EXIT_MAIN_LOOP)) {
+@@ -1643,6 +1537,9 @@ dev_close:
+ 			pthread_cond_broadcast(&nic->disable_wait_cond);
+ 		}
+ 	}
++	/* clean up the nic flags */
++	nic->flags &= ~NIC_ENABLED_PENDING;
++
+ 	pthread_mutex_unlock(&nic->nic_mutex);
+ 
+ 	LOG_INFO(PFX "%s: nic loop thread exited", nic->log_name);
+diff --git a/src/unix/nic.h b/src/unix/nic.h
+index 57d89b4..da900c5 100644
+--- a/src/unix/nic.h
++++ b/src/unix/nic.h
+@@ -67,6 +67,8 @@ extern struct nic_lib_handle *nic_lib_list;
+ extern pthread_mutex_t nic_list_mutex;
+ extern struct nic *nic_list;
+ 
++extern void *nl_process_handle_thread(void *arg);
++
+ /*******************************************************************************
+  *  Constants
+  ******************************************************************************/
+@@ -117,20 +119,30 @@ struct nic_stats {
+  * NIC interface structure
+  ******************************************************************************/
+ typedef struct nic_interface {
++	struct nic_interface *vlan_next;
+ 	struct nic_interface *next;
+ 	struct nic *parent;
+ 
+ 	uint16_t protocol;
+ 	uint16_t flags;
+-#define NIC_IFACE_PERSIST	0x0001
++#define NIC_IFACE_PERSIST	(1<<0)
++#define NIC_IFACE_ACQUIRE	(1<<1)
++#define NIC_IFACE_PATHREQ_WAIT1	(1<<2)
++#define NIC_IFACE_PATHREQ_WAIT2 (1<<3)
++#define NIC_IFACE_PATHREQ_WAIT	(NIC_IFACE_PATHREQ_WAIT1 | \
++				 NIC_IFACE_PATHREQ_WAIT2)
+ 	uint8_t mac_addr[ETH_ALEN];
+ 	uint8_t vlan_priority;
+ 	uint16_t vlan_id;
++#define NO_VLAN		0x8000
+ 
++	uint16_t mtu;
+ 	time_t start_time;
+ 
+ 	struct uip_stack ustack;
+-	struct nic_interface *vlan_next;
++
++	int iface_num;
++	int request_type;
+ } nic_interface_t;
+ 
+ /******************************************************************************
+@@ -178,8 +190,9 @@ typedef struct nic_ops {
+ 	int (*clear_tx_intr) (struct nic *);
+ 	int (*handle_iscsi_path_req) (struct nic *,
+ 				      int,
+-				      struct iscsi_uevent * ev,
+-				      struct iscsi_path * path);
++				      struct iscsi_uevent *ev,
++				      struct iscsi_path *path,
++				      nic_interface_t *nic_iface);
+ } net_ops_t;
+ 
+ typedef struct nic_lib_handle {
+@@ -199,6 +212,9 @@ typedef struct nic {
+ #define NIC_DISABLED		0x0008
+ #define NIC_IPv6_ENABLED	0x0010
+ #define NIC_ADDED_MULICAST	0x0020
++#define NIC_LONG_SLEEP		0x0040
++#define NIC_PATHREQ_WAIT	0x0080
++
+ #define NIC_VLAN_STRIP_ENABLED	0x0100
+ #define NIC_MSIX_ENABLED	0x0200
+ #define NIC_TX_HAS_SENT		0x0400
+@@ -214,7 +230,6 @@ typedef struct nic {
+ #define NIC_STOPPED		0x0001
+ #define NIC_STARTED_RUNNING	0x0002
+ #define NIC_RUNNING		0x0004
+-#define NIC_LONG_SLEEP		0x0008
+ #define NIC_EXIT		0x0010
+ 
+ 	int fd;			/* Holds the file descriptor to UIO */
+@@ -232,6 +247,7 @@ typedef struct nic {
+ 
+ 	uint32_t intr_count;	/* Total UIO interrupt count            */
+ 
++	/* Held for nic ops manipulation */
+ 	pthread_mutex_t nic_mutex;
+ 
+ 	/*  iSCSI ring ethernet MAC address */
+@@ -268,6 +284,7 @@ typedef struct nic {
+ 
+ 	/*  Number of retrys from iscsid */
+ 	uint32_t pending_count;
++	uint32_t pathreq_pending_count;
+ 
+ #define DEFAULT_RX_POLL_USEC	100	/* usec */
+ 	/* options enabled by the user */
+@@ -295,6 +312,19 @@ typedef struct nic {
+ 	int (*process_intr) (struct nic * nic);
+ 
+ 	struct nic_ops *ops;
++
++	/* NL processing parameters */
++	pthread_t nl_process_thread;
++	pthread_cond_t nl_process_cond;
++	pthread_cond_t nl_process_if_down_cond;
++	pthread_mutex_t nl_process_mutex;
++	int nl_process_if_down;
++	int nl_process_head;
++	int nl_process_tail;
++#define NIC_NL_PROCESS_MAX_RING_SIZE        128
++#define NIC_NL_PROCESS_LAST_ENTRY           (NIC_NL_PROCESS_MAX_RING_SIZE - 1)
++#define NIC_NL_PROCESS_NEXT_ENTRY(x) ((x + 1) & NIC_NL_PROCESS_MAX_RING_SIZE)
++	void *nl_process_ring[NIC_NL_PROCESS_MAX_RING_SIZE];
+ } nic_t;
+ 
+ /******************************************************************************
+@@ -307,8 +337,6 @@ void nic_add(nic_t *nic);
+ int nic_remove(nic_t *nic);
+ 
+ int nic_add_nic_iface(nic_t *nic, nic_interface_t *nic_iface);
+-int nic_add_vlan_iface(nic_t *nic, nic_interface_t *nic_iface,
+-		       nic_interface_t *vlan_iface);
+ int nic_process_intr(nic_t *nic, int discard_check);
+ 
+ nic_interface_t *nic_iface_init();
+@@ -339,14 +367,6 @@ int enable_multicast(nic_t * nic);
+ int disable_multicast(nic_t * nic);
+ 
+ void nic_set_all_nic_iface_mac_to_parent(nic_t * nic);
+-struct nic_interface *nic_find_nic_iface(nic_t * nic, uint16_t vlan_id);
+-struct nic_interface *nic_find_nic_iface_protocol(nic_t * nic,
+-						  uint16_t vlan_id,
+-						  uint16_t protocol);
+-struct nic_interface *nic_find_vlan_iface_protocol(nic_t *nic,
+-						   nic_interface_t *nic_iface,
+-						   uint16_t vlan_id,
+-						   uint16_t protocol);
+ int find_nic_lib_using_pci_id(uint32_t vendor, uint32_t device,
+ 			      uint32_t subvendor, uint32_t subdevice,
+ 			      nic_lib_handle_t ** handle,
+diff --git a/src/unix/nic_nl.c b/src/unix/nic_nl.c
+index 971f350..34e2062 100644
+--- a/src/unix/nic_nl.c
++++ b/src/unix/nic_nl.c
+@@ -83,20 +83,6 @@ const static struct sockaddr_nl dest_addr = {
+ /* Netlink */
+ int nl_sock = INVALID_FD;
+ 
+-/*  Items used to handle the thread used to send/process ARP's */
+-static pthread_t nl_process_thread;
+-static pthread_cond_t nl_process_cond;
+-pthread_cond_t nl_process_if_down_cond;
+-pthread_mutex_t nl_process_mutex;
+-int nl_process_if_down = 0;
+-
+-#define NL_PROCESS_MAX_RING_SIZE	128
+-#define NL_PROCESS_LAST_ENTRY		NL_PROCESS_MAX_RING_SIZE - 1
+-#define NL_PROCESS_NEXT_ENTRY(x) ((x + 1) & NL_PROCESS_MAX_RING_SIZE)
+-static int nl_process_head;
+-static int nl_process_tail;
+-static void *nl_process_ring[NL_PROCESS_MAX_RING_SIZE];
+-
+ #define MAX_TX_DESC_CNT (TX_DESC_CNT - 1)
+ 
+ #define NEXT_TX_BD(x) (((x) & (MAX_TX_DESC_CNT - 1)) ==                 \
+@@ -222,10 +208,11 @@ int __kipc_call(int fd, void *iov_base, int iov_len)
+ static int pull_from_nl(char **buf)
+ {
+ 	int rc;
+-	size_t ev_size;
++	size_t ev_size, payload_size, alloc_size;
+ 	char nlm_ev[NLMSG_SPACE(sizeof(struct iscsi_uevent))];
+ 	struct nlmsghdr *nlh;
+ 	char *data = NULL;
++	struct iscsi_uevent *ev;
+ 
+ 	/*  Take a quick peek at what how much uIP will need to read */
+ 	rc = nl_read(nl_sock, nlm_ev,
+@@ -249,14 +236,26 @@ static int pull_from_nl(char **buf)
+ 		return -EINVAL;
+ 	}
+ 
+-	data = (char *)malloc(nlh->nlmsg_len);
++	ev = (struct iscsi_uevent *)NLMSG_DATA(nlh);
++	if (ev->type == ISCSI_KEVENT_PATH_REQ) {
++		ev_size = nlh->nlmsg_len - NLMSG_ALIGN(sizeof(struct nlmsghdr));
++		payload_size = ev_size - sizeof(struct iscsi_uevent);
++		if (payload_size < sizeof(struct iscsi_path))
++			alloc_size = nlh->nlmsg_len + (payload_size -
++				     sizeof(struct iscsi_path));
++		else
++			alloc_size = nlh->nlmsg_len;
++	} else {
++		alloc_size = nlh->nlmsg_len;
++	}
++	data = (char *)malloc(alloc_size);
+ 	if (unlikely(data == NULL)) {
+ 		LOG_ERR(PFX "Couldn't allocate %d bytes for Netlink "
+-			"iSCSI message", nlh->nlmsg_len);
++			"iSCSI message", alloc_size);
+ 		return -ENOMEM;
+ 	}
+ 
+-	memset(data, 0, nlh->nlmsg_len);
++	memset(data, 0, alloc_size);
+ 	ev_size = nlh->nlmsg_len - NLMSG_ALIGN(sizeof(struct nlmsghdr));
+ 	rc = nl_read(nl_sock, data, (int)nlh->nlmsg_len, MSG_WAITALL);
+ 	if (rc <= 0) {
+@@ -269,10 +268,9 @@ static int pull_from_nl(char **buf)
+ 
+ 		goto error;
+ 	}
+-
+ 	*buf = data;
+ 	return 0;
+-      error:
++error:
+ 	if (data != NULL)
+ 		free(data);
+ 
+@@ -284,9 +282,8 @@ const static struct timespec ctldev_sleep_req = {
+ 	.tv_nsec = 250000000,
+ };
+ 
+-static int ctldev_handle(char *data)
++static int ctldev_handle(char *data, nic_t *nic)
+ {
+-	nic_t *nic = NULL;
+ 	int rc;
+ 	struct iscsi_uevent *ev;
+ 	uint8_t *payload;
+@@ -294,18 +291,12 @@ static int ctldev_handle(char *data)
+ 	char *msg_type_str;
+ 	uint32_t host_no;
+ 	int i;
++	nic_interface_t *nic_iface = NULL;
+ 
+ 	ev = (struct iscsi_uevent *)NLMSG_DATA(data);
+ 	switch (ev->type) {
+ 	case ISCSI_KEVENT_PATH_REQ:
+ 		msg_type_str = "path_req";
+-
+-		host_no = ev->r.req_path.host_no;
+-		break;
+-	case ISCSI_KEVENT_IF_DOWN:
+-		msg_type_str = "if_down";
+-
+-		host_no = ev->r.notify_if_down.host_no;
+ 		break;
+ 	default:
+ 		/*  We don't care about other iSCSI Netlink messages */
+@@ -315,22 +306,16 @@ static int ctldev_handle(char *data)
+ 	}
+ 
+ 	/*  This is a message that drivers should be interested in */
+-	LOG_INFO("Received: '%s': host_no: %d", msg_type_str, host_no);
+-
+-	rc = from_host_no_find_associated_eth_device(host_no, &nic);
+-	if (rc != 0) {
+-		LOG_ERR(PFX "Dropping msg, couldn't find nic with host no:%d",
+-			host_no);
+-		goto error;
+-	}
++	LOG_INFO(PFX "%s: Processing '%s'", nic->log_name, msg_type_str);
+ 
+ 	payload = (uint8_t *) ((uint8_t *) ev) + sizeof(*ev);
+ 	path = (struct iscsi_path *)payload;
+ 
+ 	if (ev->type == ISCSI_KEVENT_PATH_REQ) {
+ 		struct timespec sleep_rem;
+-		nic_interface_t *nic_iface, *vlan_iface;
++		nic_interface_t *vlan_iface;
+ 		uint16_t ip_type;
++		int iface_num, vlan_id;
+ 
+ 		if (path->ip_addr_len == 4)
+ 			ip_type = AF_INET;
+@@ -339,67 +324,107 @@ static int ctldev_handle(char *data)
+ 		else
+ 			ip_type = 0;
+ 
+-		/* Find the parent nic_iface */
+-		nic_iface = nic_find_nic_iface_protocol(nic, 0,	ip_type);
++		/* Find the nic_iface to use */
++		iface_num = ev->r.req_path.iface_num ?
++			    ev->r.req_path.iface_num : IFACE_NUM_INVALID;
++		vlan_id = path->vlan_id ? path->vlan_id : NO_VLAN;
++
++		LOG_DEBUG(PFX "%s: PATH_REQ with iface_num %d VLAN %d",
++			  nic->log_name, iface_num, vlan_id);
++
++		pthread_mutex_lock(&nic->nic_mutex);
++
++		nic_iface = nic_find_nic_iface(nic, ip_type, vlan_id,
++					       iface_num, IP_CONFIG_OFF);
+ 		if (nic_iface == NULL) {
+-			LOG_ERR(PFX "%s: Couldn't find nic iface "
+-				"vlan: %d ip_type: %d "
+-				"ip_addr_len: %d to clone",
+-				nic->log_name, path->vlan_id, ip_type,
+-				path->ip_addr_len);
+-			goto error;
+-		}
+-		if (path->vlan_id) {
+-			vlan_iface = nic_find_vlan_iface_protocol(nic,
+-					nic_iface, path->vlan_id, ip_type);
+-			if (vlan_iface == NULL) {
+-				/* Create a vlan_iface */
+-				vlan_iface = nic_iface_init();
+-				if (vlan_iface == NULL) {
+-					LOG_ERR(PFX "%s: Couldn't allocate "
+-						"space for vlan: %d ip_type: "
+-						"%d ip_addr_len: %d",
+-						nic->log_name, path->vlan_id,
+-						ip_type, path->ip_addr_len);
+-					goto error;
++			nic_iface = nic_find_nic_iface(nic, ip_type,
++						       NO_VLAN,
++						       IFACE_NUM_INVALID,
++						       IP_CONFIG_OFF);
++			if (nic_iface == NULL) {
++				pthread_mutex_unlock(&nic->nic_mutex);
++				LOG_ERR(PFX "%s: Couldn't find nic iface parent"
++					" vlan: %d ip_type: %d "
++					"ip_addr_len: %d to clone",
++					nic->log_name, path->vlan_id, ip_type,
++					path->ip_addr_len);
++				goto error;
++			}
++			if (nic_iface->iface_num != IFACE_NUM_INVALID) {
++				/* New VLAN support:
++				   Use the nic_iface found from the top
++				   of the protocol family and ignore
++				   the VLAN id from the path_req */
++				if (!(nic_iface->iface_num == 0 &&
++				      nic_iface->vlan_id == 0 &&
++				      path->vlan_id)) {
++					pthread_mutex_unlock(&nic->nic_mutex);
++					goto nic_iface_done;
+ 				}
+-
+-				vlan_iface->protocol = ip_type;
+-				vlan_iface->vlan_id = path->vlan_id;
+-				nic_add_vlan_iface(nic, nic_iface, vlan_iface);
+-
+-				/* TODO: When VLAN support is placed in */
+-				/* the iface file revisit this code */
+-				vlan_iface->ustack.ip_config =
+-					nic_iface->ustack.ip_config;
+-				memcpy(vlan_iface->ustack.hostaddr,
+-				       nic_iface->ustack.hostaddr,
+-				       sizeof(nic_iface->ustack.hostaddr));
+-				memcpy(vlan_iface->ustack.netmask,
+-				       nic_iface->ustack.netmask,
+-				       sizeof(nic_iface->ustack.netmask));
+-				memcpy(vlan_iface->ustack.netmask6,
+-				       nic_iface->ustack.netmask6,
+-				       sizeof(nic_iface->ustack.netmask6));
+-				memcpy(vlan_iface->ustack.hostaddr6,
+-				       nic_iface->ustack.hostaddr6,
+-				       sizeof(nic_iface->ustack.hostaddr6));
+-
+-				persist_all_nic_iface(nic);
+-				nic_disable(nic, 0);
+-				nic_iface = vlan_iface;
++				/* If iface_num == 0 and vlan_id == 0 but
++				   the vlan_id from path_req is > 0,
++				   then fallthru to the legacy support since
++				   this is most likely from an older iscsid
++				   (RHEL6.2/6.3 but has iface_num support)
++				*/
+ 			}
+-		}
++			/* Legacy VLAN support:
++			   This newly created nic_iface must inherit the
++			   network parameters from the parent nic_iface
++			*/
++			LOG_DEBUG(PFX "%s: Created the nic_iface for vlan: %d "
++				  "ip_type: %d", nic->log_name, path->vlan_id,
++				  ip_type);
++			vlan_iface = nic_iface_init();
++			if (vlan_iface == NULL) {
++				pthread_mutex_unlock(&nic->nic_mutex);
++				LOG_ERR(PFX "%s: Couldn't allocate "
++					"space for vlan: %d ip_type: "
++					"%d", nic->log_name, path->vlan_id,
++					ip_type);
++				goto error;
++			}
++			vlan_iface->protocol = ip_type;
++			vlan_iface->vlan_id = path->vlan_id;
++			nic_add_nic_iface(nic, vlan_iface);
++
++			vlan_iface->ustack.ip_config =
++				nic_iface->ustack.ip_config;
++			memcpy(vlan_iface->ustack.hostaddr,
++			       nic_iface->ustack.hostaddr,
++			       sizeof(nic_iface->ustack.hostaddr));
++			memcpy(vlan_iface->ustack.netmask,
++			       nic_iface->ustack.netmask,
++			       sizeof(nic_iface->ustack.netmask));
++			memcpy(vlan_iface->ustack.netmask6,
++			       nic_iface->ustack.netmask6,
++			       sizeof(nic_iface->ustack.netmask6));
++			memcpy(vlan_iface->ustack.hostaddr6,
++			       nic_iface->ustack.hostaddr6,
++			       sizeof(nic_iface->ustack.hostaddr6));
++
++			/* Persist so when nic_close won't call uip_reset
++			   to nullify nic_iface->ustack */
++			persist_all_nic_iface(nic);
++
++			nic_iface = vlan_iface;
++
++			pthread_mutex_unlock(&nic->nic_mutex);
+ 
++			/* nic_disable but not going down */
++			nic_disable(nic, 0);
++		} else {
++			pthread_mutex_unlock(&nic->nic_mutex);
++		}
++nic_iface_done:
+ 		/*  Force enable the NIC */
+-		if ((nic->state & NIC_STOPPED) &&
+-		    !(nic->flags & NIC_ENABLED_PENDING))
++		if (nic->state == NIC_STOPPED)
+ 			nic_enable(nic);
+ 
+ 		/*  Ensure that the NIC is RUNNING */
+ 		rc = -EIO;
+ 		for (i = 0; i < 10; i++) {
+-			if ((nic->state & NIC_RUNNING) == NIC_RUNNING) {
++			if (nic->state == NIC_RUNNING) {
+ 				rc = 0;
+ 				break;
+ 			}
+@@ -418,49 +443,25 @@ static int ctldev_handle(char *data)
+ 	}
+ 
+ 	if (nic->ops) {
+-		char eth_device_name[IFNAMSIZ];
+-
+ 		switch (ev->type) {
+ 		case ISCSI_KEVENT_PATH_REQ:
+ 			/*  pass the request up to the user space
+ 			 *  library driver */
+-			if (nic->ops->handle_iscsi_path_req) {
++			nic_iface->flags |= NIC_IFACE_PATHREQ_WAIT2;
++			nic_iface->flags &= ~NIC_IFACE_PATHREQ_WAIT1;
++			if (nic->ops->handle_iscsi_path_req)
+ 				nic->ops->handle_iscsi_path_req(nic,
+ 								nl_sock, ev,
+-								path);
+-			}
+-
+-			LOG_INFO(PFX "%s: 'path_req' operation finished",
+-				 nic->log_name);
+-
+-			rc = 0;
+-			break;
+-		case ISCSI_KEVENT_IF_DOWN:
+-			memcpy(eth_device_name, nic->eth_device_name,
+-			       sizeof(eth_device_name));
+-
+-			pthread_mutex_lock(&nic_list_mutex);
+-
++								path,
++								nic_iface);
++			nic_iface->flags &= ~NIC_IFACE_PATHREQ_WAIT;
+ 			pthread_mutex_lock(&nic->nic_mutex);
+-			nic->flags |= NIC_EXIT_MAIN_LOOP;
++			nic->flags &= ~NIC_PATHREQ_WAIT;
+ 			pthread_mutex_unlock(&nic->nic_mutex);
+-
+-			pthread_cond_broadcast(&nic->enable_done_cond);
+-
+-			nic_disable(nic, 1);
+-
+-			nic_remove(nic);
+-			pthread_mutex_unlock(&nic_list_mutex);
+-
+-			pthread_mutex_lock(&nl_process_mutex);
+-			nl_process_if_down = 0;
+-			pthread_mutex_unlock(&nl_process_mutex);
++			LOG_INFO(PFX "%s: 'path_req' operation finished",
++				 nic->log_name);
+ 
+ 			rc = 0;
+-
+-			LOG_INFO(PFX "%s: 'if_down' operation finished",
+-				 eth_device_name);
+-
+ 			break;
+ 		default:
+ 			rc = -EAGAIN;
+@@ -468,55 +469,62 @@ static int ctldev_handle(char *data)
+ 		}
+ 	}
+ 
+-      error:
++error:
+ 
+ 	return rc;
+ }
+ 
+-static void *nl_process_handle_thread(void *arg)
++/* NIC specific nl processing thread */
++void *nl_process_handle_thread(void *arg)
+ {
+ 	int rc;
++	nic_t *nic = (nic_t *)arg;
++
++	if (nic == NULL)
++		goto error;
+ 
+ 	while (!event_loop_stop) {
+ 		char *data = NULL;
+ 
+-		rc = pthread_cond_wait(&nl_process_cond, &nl_process_mutex);
++		rc = pthread_cond_wait(&nic->nl_process_cond,
++				       &nic->nl_process_mutex);
+ 		if (rc != 0) {
+ 			LOG_ERR("Fatal error in NL processing thread "
+ 				"during wait[%s]", strerror(rc));
+ 			break;
+ 		}
+ 
+-		data = nl_process_ring[nl_process_head];
+-		nl_process_ring[nl_process_head] = NULL;
+-		nl_process_tail = NL_PROCESS_NEXT_ENTRY(nl_process_tail);
++		data = nic->nl_process_ring[nic->nl_process_head];
++		nic->nl_process_ring[nic->nl_process_head] = NULL;
++		nic->nl_process_tail =
++				NIC_NL_PROCESS_NEXT_ENTRY(nic->nl_process_tail);
+ 
+-		pthread_mutex_unlock(&nl_process_mutex);
++		pthread_mutex_unlock(&nic->nl_process_mutex);
+ 
+ 		if (data) {
+-			ctldev_handle(data);
++			ctldev_handle(data, nic);
+ 			free(data);
+ 		}
+ 	}
+-
++error:
+ 	return NULL;
+ }
+ 
+-static void flush_nl_process_ring()
++static void flush_nic_nl_process_ring(nic_t *nic)
+ {
+ 	int i;
+ 
+-	for (i = 0; i < NL_PROCESS_MAX_RING_SIZE; i++) {
+-		if (nl_process_ring[i] != NULL) {
+-			free(nl_process_ring[i]);
+-			nl_process_ring[i] = NULL;
++	for (i = 0; i < NIC_NL_PROCESS_MAX_RING_SIZE; i++) {
++		if (nic->nl_process_ring[i] != NULL) {
++			free(nic->nl_process_ring[i]);
++			nic->nl_process_ring[i] = NULL;
+ 		}
+ 	}
+ 
+-	nl_process_head = 0;
+-	nl_process_tail = 0;
++	nic->nl_process_head = 0;
++	nic->nl_process_tail = 0;
+ 
+-	LOG_DEBUG(PFX "Flushed NL ring");
++	LOG_DEBUG(PFX "%s: Flushed NIC NL ring", nic->log_name);
+ }
+ 
+ /**
+@@ -528,25 +536,9 @@ static void flush_nl_process_ring()
+ int nic_nl_open()
+ {
+ 	int rc;
++	char *msg_type_str;
+ 
+-	/*  Prepare the thread to issue the ARP's */
+-	nl_process_head = 0;
+-	nl_process_tail = 0;
+-	nl_process_if_down = 0;
+-	memset(&nl_process_ring, 0, sizeof(nl_process_ring));
+-
+-	pthread_mutex_init(&nl_process_mutex, NULL);
+-	pthread_cond_init(&nl_process_cond, NULL);
+-	pthread_cond_init(&nl_process_if_down_cond, NULL);
+-
+-	rc = pthread_create(&nl_process_thread, NULL,
+-			    nl_process_handle_thread, NULL);
+-	if (rc != 0) {
+-		LOG_ERR("Could not create NL processing thread [%s]",
+-			strerror(rc));
+-		return -EIO;
+-	}
+-
++	/* Prepare the thread to issue the ARP's */
+ 	nl_sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ISCSI);
+ 	if (nl_sock < 0) {
+ 		LOG_ERR(PFX "can not create NETLINK_ISCSI socket [%s]",
+@@ -581,6 +573,8 @@ int nic_nl_open()
+ 	while (!event_loop_stop) {
+ 		struct iscsi_uevent *ev;
+ 		char *buf = NULL;
++		uint32_t host_no;
++		nic_t *nic;
+ 
+ 		rc = pull_from_nl(&buf);
+ 		if (rc != 0)
+@@ -588,33 +582,91 @@ int nic_nl_open()
+ 
+ 		/*  Try to abort ARP'ing if a if_down was recieved */
+ 		ev = (struct iscsi_uevent *)NLMSG_DATA(buf);
+-		if (ev->type == ISCSI_KEVENT_IF_DOWN) {
+-			LOG_INFO(PFX "Received if_down event");
++		switch (ev->type) {
++		case ISCSI_KEVENT_IF_DOWN:
++			host_no = ev->r.notify_if_down.host_no;
++			msg_type_str = "if_down";
++			break;
++		case ISCSI_KEVENT_PATH_REQ:
++			host_no = ev->r.req_path.host_no;
++			msg_type_str = "path_req";
++			break;
++		default:
++			/*  We don't care about other iSCSI Netlink messages */
++			continue;
++		}
++		LOG_INFO(PFX "Received %s for host %d", msg_type_str, host_no);
+ 
+-			pthread_mutex_lock(&nl_process_mutex);
+-			/* Don't flush the nl ring if another if_down
+-			   is in progress */
+-			if (!nl_process_if_down) {
+-				nl_process_if_down = 1;
++		/* Make sure the nic list doesn't get yanked */
++		pthread_mutex_lock(&nic_list_mutex);
+ 
+-				flush_nl_process_ring();
+-			}
+-			pthread_mutex_unlock(&nl_process_mutex);
++		rc = from_host_no_find_associated_eth_device(host_no, &nic);
++		if (rc != 0) {
++			pthread_mutex_unlock(&nic_list_mutex);
++			LOG_ERR(PFX "Dropping msg, couldn't find nic with host "
++				"no: %d", host_no);
++			continue;
++		}
++
++		/* Found the nic */
++		if (nic->nl_process_thread == INVALID_THREAD) {
++			/* If thread is not valid, just drop it */
++			pthread_mutex_unlock(&nic_list_mutex);
++			LOG_ERR(PFX "Dropping msg, nic nl process thread "
++				"not ready for host no: %d", host_no);
++			continue;
+ 		}
+ 
+-		if ((nl_process_head + 1 == nl_process_tail) ||
+-		    (nl_process_tail == 0 &&
+-		     nl_process_head == NL_PROCESS_LAST_ENTRY)) {
+-			LOG_WARN(PFX "No space on Netlink ring");
++		if (ev->type == ISCSI_KEVENT_IF_DOWN) {
++			char eth_device_name[IFNAMSIZ];
++
++			pthread_mutex_lock(&nic->nl_process_mutex);
++			nic->nl_process_if_down = 1;
++			flush_nic_nl_process_ring(nic);
++			pthread_cond_broadcast(&nic->nl_process_if_down_cond);
++			pthread_mutex_unlock(&nic->nl_process_mutex);
++
++			memcpy(eth_device_name, nic->eth_device_name,
++			       sizeof(eth_device_name));
++
++			pthread_mutex_lock(&nic->nic_mutex);
++			nic->flags &= ~NIC_PATHREQ_WAIT;
++			nic->flags |= NIC_EXIT_MAIN_LOOP;
++			pthread_cond_broadcast(&nic->enable_done_cond);
++			pthread_mutex_unlock(&nic->nic_mutex);
++
++			pthread_mutex_lock(&nic->nl_process_mutex);
++			nic->nl_process_if_down = 0;
++			pthread_mutex_unlock(&nic->nl_process_mutex);
++
++			nic_disable(nic, 1);
++
++			nic_remove(nic);
++			pthread_mutex_unlock(&nic_list_mutex);
++
++			LOG_INFO(PFX "%s: 'if_down' operation finished",
++				 eth_device_name);
++			continue;
++		}
++		/* Place msg into the nic specific queue */
++		pthread_mutex_lock(&nic->nl_process_mutex);
++		if ((nic->nl_process_head + 1 == nic->nl_process_tail) ||
++		    (nic->nl_process_tail == 0 &&
++		     nic->nl_process_head == NIC_NL_PROCESS_LAST_ENTRY)) {
++			pthread_mutex_unlock(&nic->nl_process_mutex);
++			pthread_mutex_unlock(&nic_list_mutex);
++			LOG_WARN(PFX "%s: No space on Netlink ring",
++				 nic->log_name);
+ 			continue;
+ 		}
++		nic->nl_process_ring[nic->nl_process_head] = buf;
++		nic->nl_process_head =
++				NIC_NL_PROCESS_NEXT_ENTRY(nic->nl_process_head);
++		pthread_cond_signal(&nic->nl_process_cond);
+ 
+-		pthread_mutex_lock(&nl_process_mutex);
+-		nl_process_ring[nl_process_head] = buf;
+-		nl_process_head = NL_PROCESS_NEXT_ENTRY(nl_process_head);
++		pthread_mutex_unlock(&nic->nl_process_mutex);
+ 
+-		pthread_cond_signal(&nl_process_cond);
+-		pthread_mutex_unlock(&nl_process_mutex);
++		pthread_mutex_unlock(&nic_list_mutex);
+ 
+ 		LOG_DEBUG(PFX "Pulled nl event");
+ 	}
+diff --git a/src/unix/nic_utils.c b/src/unix/nic_utils.c
+index fe58df8..a1d3e72 100644
+--- a/src/unix/nic_utils.c
++++ b/src/unix/nic_utils.c
+@@ -65,7 +65,7 @@
+  *****************************************************************************/
+ static const char nic_uio_sysfs_name_tempate[] = "/sys/class/uio/uio%i/name";
+ static const char cnic_sysfs_uio_event_template[] =
+-    "/sys/class/uio/uio%d/event";
++	"/sys/class/uio/uio%d/event";
+ static const char base_uio_sysfs_name[] = "/sys/class/uio/";
+ static const char uio_name[] = "uio";
+ 
+@@ -77,7 +77,7 @@ static const char base_iscsi_host_name[] = "/sys/class/iscsi_host/";
+ static const char host_template[] = "host%d";
+ static const char iscsi_host_path_template[] = "/sys/class/iscsi_host/host%d";
+ static const char iscsi_host_path_netdev_template[] =
+-    "/sys/class/iscsi_host/host%d/netdev";
++	"/sys/class/iscsi_host/host%d/netdev";
+ static const char cnic_uio_sysfs_resc_template[] =
+ 	"/sys/class/uio/uio%i/device/resource%i";
+ 
+@@ -208,6 +208,7 @@ int nic_discover_iscsi_hosts()
+ 
+ 	default:
+ 		/*  There are iSCSI hosts */
++		pthread_mutex_lock(&nic_list_mutex);
+ 		for (i = 0; i < count; i++) {
+ 			int host_no;
+ 			char *raw = NULL;
+@@ -267,6 +268,7 @@ int nic_discover_iscsi_hosts()
+ 
+ 			free(raw);
+ 		}
++		pthread_mutex_unlock(&nic_list_mutex);
+ 
+ 		/*  Cleanup the scandir() call */
+ 		for (i = 0; i < count; i++)
+@@ -402,6 +404,7 @@ static char *extract_none(struct dirent **files)
+ /**
+  *  from_host_no_find_nic() - Given the host number
+  *      this function will try to find the assoicated nic interface
++ *  Must be called with nic_list_mutex lock
+  *  @param host_no - minor number of the UIO device
+  *  @param nic - pointer to the NIC will set if successful
+  *  @return 0 on success, <0 on error
+@@ -431,7 +434,6 @@ int from_host_no_find_associated_eth_device(int host_no, nic_t ** nic)
+ 
+ 	rc = -EIO;
+ 
+-	pthread_mutex_lock(&nic_list_mutex);
+ 	current_nic = nic_list;
+ 	while (current_nic != NULL) {
+ 		if (strcmp(raw, current_nic->eth_device_name) == 0) {
+@@ -442,7 +444,6 @@ int from_host_no_find_associated_eth_device(int host_no, nic_t ** nic)
+ 
+ 		current_nic = current_nic->next;
+ 	}
+-	pthread_mutex_unlock(&nic_list_mutex);
+ 
+ 	free(raw);
+ 
+@@ -923,7 +924,7 @@ int nic_enable(nic_t * nic)
+ 			 nic->log_name, nic->flags, nic->state);
+ 		return -EINVAL;
+ 	}
+-	if (nic->state & NIC_STOPPED) {
++	if (nic->state == NIC_STOPPED) {
+ 		struct timespec ts;
+ 		struct timeval tp;
+ 		int rc;
+@@ -940,48 +941,20 @@ int nic_enable(nic_t * nic)
+ 		rc = gettimeofday(&tp, NULL);
+ 		ts.tv_sec = tp.tv_sec;
+ 		ts.tv_nsec = tp.tv_usec * 1000;
+-		ts.tv_sec += 10;
++		ts.tv_sec += 100;
+ 
+ 		/*  Wait for the device to be enabled */
+ 		rc = pthread_cond_timedwait(&nic->enable_done_cond,
+ 					    &nic->nic_mutex, &ts);
+-#if 0
+-		if (rc || !nic->flags & NIC_ENABLED) {
+-			/* Give it one more shout */
+-			pthread_cond_broadcast(&nic->enable_wait_cond);
+-			rc = gettimeofday(&tp, NULL);
+-			ts.tv_sec = tp.tv_sec;
+-			ts.tv_nsec = tp.tv_usec * 1000;
+-			ts.tv_sec += 5;
+-			rc = pthread_cond_timedwait(&nic->enable_done_cond,
+-						    &nic->nic_mutex, &ts);
+-		}
+-#endif
+-		nic->flags &= ~NIC_ENABLED_PENDING;
+-
+ 		if (rc == 0 && nic->flags & NIC_ENABLED) {
+ 			LOG_DEBUG(PFX "%s: device enabled", nic->log_name);
+ 		} else {
+-			LOG_ERR(PFX "%s: waiting to finish nic_enable err:%s",
++			nic->flags &= ~NIC_ENABLED;
++			nic->flags |= NIC_DISABLED;
++			nic->flags &= ~NIC_ENABLED_PENDING;
++
++			LOG_ERR(PFX "%s: waiting to finish nic_enable err: %s",
+ 				nic->log_name, strerror(rc));
+-			/* Must clean up the ustack */
+-			nic_interface_t *nic_iface = nic->nic_iface;
+-			nic_interface_t *vlan_iface;
+-			while (nic_iface != NULL) {
+-				LOG_INFO(PFX "%s: resetting uIP stack",
+-					 nic->log_name);
+-				uip_reset(&nic_iface->ustack);
+-				vlan_iface = nic_iface->vlan_next;
+-				while (vlan_iface != NULL) {
+-					LOG_INFO(PFX "%s: resetting "
+-						 "vlan uIP stack",
+-						 nic->log_name);
+-					uip_reset(&vlan_iface->ustack);
+-					vlan_iface =
+-						vlan_iface->vlan_next;
+-				}
+-				nic_iface = nic_iface->next;
+-			}
+ 		}
+ 		pthread_mutex_unlock(&nic->nic_mutex);
+ 
+@@ -1001,7 +974,8 @@ int nic_enable(nic_t * nic)
+  */
+ int nic_disable(nic_t * nic, int going_down)
+ {
+-	if (nic->state & (NIC_STARTED_RUNNING | NIC_RUNNING)) {
++	if (nic->state == NIC_STARTED_RUNNING ||
++	    nic->state == NIC_RUNNING) {
+ 		struct timespec ts;
+ 		struct timeval tp;
+ 		int rc;
+@@ -1012,8 +986,7 @@ int nic_disable(nic_t * nic, int going_down)
+ 		nic->flags &= ~NIC_ENABLED;
+ 		nic->flags |= NIC_DISABLED;
+ 		nic->flags &= ~NIC_STARTED_RUNNING;
+-		nic->state &= ~NIC_RUNNING;
+-		nic->state |= NIC_STOPPED;
++		nic->state = NIC_STOPPED;
+ 
+ 		if (going_down)
+ 			nic->flags |= NIC_GOING_DOWN;
+@@ -1070,7 +1043,9 @@ void nic_remove_all()
+ 	nic = nic_list;
+ 	while (nic != NULL) {
+ 		nic_next = nic->next;
++		pthread_mutex_lock(&nic->nic_mutex);
+ 		nic_close(nic, 1, FREE_ALL_STRINGS);
++		pthread_mutex_unlock(&nic->nic_mutex);
+ 		nic_remove(nic);
+ 		nic = nic_next;
+ 	}
+@@ -1127,14 +1102,13 @@ error:
+  *  nic_set_all_nic_iface_mac_to_parent() - This is a utility function used to 
+  *      intialize all the MAC addresses of the network interfaces for a given
+  *      CNIC UIO device
++ *  Call with nic mutex held
+  *  @param dev - CNIC UIO device to initialize
+  */
+-void nic_set_all_nic_iface_mac_to_parent(nic_t * nic)
++void nic_set_all_nic_iface_mac_to_parent(nic_t *nic)
+ {
+ 	nic_interface_t *current, *vlan_current;
+ 
+-	pthread_mutex_lock(&nic->nic_mutex);
+-
+ 	current = nic->nic_iface;
+ 	while (current != NULL) {
+ 		/*  Set the initial MAC address of this interface to the parent
+@@ -1148,8 +1122,6 @@ void nic_set_all_nic_iface_mac_to_parent(nic_t * nic)
+ 		}
+ 		current = current->next;
+ 	}
+-
+-	pthread_mutex_unlock(&nic->nic_mutex);
+ }
+ 
+ /*******************************************************************************
+@@ -1272,143 +1244,144 @@ void nic_fill_ethernet_header(nic_interface_t * nic_iface,
+  *  NIC interface management utility functions
+  ******************************************************************************/
+ /**
+- *  nic_find_nic_iface() - This function is used to find an interface from the 
+- *                         NIC
+- *  @param nic - NIC to look for network interfaces
+- *  @param vlan_id - VLAN id to look for
+- *  @return nic_iface - if found network interface with the given VLAN ID
+- *                      if not found a NULL is returned
+- */
+-nic_interface_t *nic_find_nic_iface(nic_t * nic, uint16_t vlan_id)
+-{
+-	nic_interface_t *current;
+-
+-	pthread_mutex_lock(&nic->nic_mutex);
+-
+-	current = nic->nic_iface;
+-	while (current != NULL) {
+-		if (current->vlan_id == vlan_id) {
+-			pthread_mutex_unlock(&nic->nic_mutex);
+-			return current;
+-		}
+-
+-		current = current->next;
+-	}
+-
+-	pthread_mutex_unlock(&nic->nic_mutex);
+-
+-	return NULL;
+-}
+-
+-/**
+- *  nic_find_nic_iface_protocol() - This function is used to find an interface
+- *                                  from the NIC
++ *  nic_find_nic_iface() - This function is used to find an interface
++ *                         from the NIC
+  *  @param nic - NIC to look for network interfaces
+  *  @param vlan_id - VLAN id to look for
+  *  @param protocol - either AF_INET or AF_INET6
++ *  @param iface_num - iface num to use if present
++ *  @param request_type - IPV4/6 DHCP/STATIC
+  *  @return nic_iface - if found network interface with the given VLAN ID
+  *                      if not found a NULL is returned
+  */
+-nic_interface_t *nic_find_nic_iface_protocol(nic_t * nic,
+-					     uint16_t vlan_id,
+-					     uint16_t protocol)
++nic_interface_t *nic_find_nic_iface(nic_t *nic,
++				    uint16_t protocol,
++				    uint16_t vlan_id,
++				    int iface_num,
++				    int request_type)
+ {
+-	nic_interface_t *current;
++	nic_interface_t *current = nic->nic_iface;
++	nic_interface_t *current_vlan = NULL;
+ 
+-	pthread_mutex_lock(&nic->nic_mutex);
+-
+-	current = nic->nic_iface;
+ 	while (current != NULL) {
+-		if ((current->vlan_id == vlan_id) &&
+-		    (current->protocol == protocol)) {
+-			pthread_mutex_unlock(&nic->nic_mutex);
+-			return current;
++		if (current->protocol != protocol)
++			goto next;
++
++		/* Check for iface_num first */
++		if (iface_num != IFACE_NUM_INVALID) {
++			if (current->iface_num == iface_num) {
++				/* Exception is when iface_num == 0, need to
++				   check for request_type also if !=
++				   IP_CONFIG_OFF */
++				if (!iface_num && request_type !=
++				    IP_CONFIG_OFF) {
++					if (current->request_type ==
++					    request_type)
++						goto found;
++				} else {
++					goto found;
++				}
++			}
++		} else if (vlan_id == NO_VLAN) {
++			/* Just return the top of the family */
++			goto found;
++		} else {
++			if ((current->vlan_id == vlan_id) &&
++			    ((request_type == IP_CONFIG_OFF) ||
++			    (current->request_type == request_type)))
++				goto found;
+ 		}
++		/* vlan_next loop */
++		current_vlan = current->vlan_next;
++		while (current_vlan != NULL) {
++			if (iface_num != IFACE_NUM_INVALID) {
++				if (current_vlan->iface_num == iface_num) {
++					if (!iface_num && request_type !=
++					    IP_CONFIG_OFF) {
++						if (current_vlan->request_type
++						    == request_type)
++							goto vlan_found;
++					} else {
++						goto vlan_found;
++					}
++				}
++			}
++			if ((current_vlan->vlan_id == vlan_id) &&
++			    ((request_type == IP_CONFIG_OFF) ||
++			    (current_vlan->request_type == request_type)))
++				goto vlan_found;
+ 
++			current_vlan = current_vlan->vlan_next;
++		}
++next:
+ 		current = current->next;
+ 	}
+-
+-	pthread_mutex_unlock(&nic->nic_mutex);
+-
+-	return NULL;
++vlan_found:
++	current = current_vlan;
++found:
++	return current;
+ }
+ 
++/* Called with nic mutex held */
+ void persist_all_nic_iface(nic_t * nic)
+ {
+-	nic_interface_t *current, *vlan_iface;
+-
+-	pthread_mutex_lock(&nic->nic_mutex);
++	nic_interface_t *current_vlan, *current;
+ 
+ 	current = nic->nic_iface;
+ 	while (current != NULL) {
+ 		current->flags |= NIC_IFACE_PERSIST;
+-		vlan_iface = current->vlan_next;
+-		while (vlan_iface != NULL) {
+-			vlan_iface->flags |= NIC_IFACE_PERSIST;
+-			vlan_iface = vlan_iface->vlan_next;
++		current_vlan = current->vlan_next;
++		while (current_vlan != NULL) {
++			current_vlan->flags |= NIC_IFACE_PERSIST;
++			current_vlan = current_vlan->vlan_next;
+ 		}
+ 		current = current->next;
+ 	}
+-
+-	pthread_mutex_unlock(&nic->nic_mutex);
+-}
+-
+-/**
+- *  nic_find_vlan_iface_protocol() - This function is used to find an interface
+- *                                   from the NIC
+- *  @param nic_iface - Base NIC to look for the vlan interfaces
+- *  @param vlan_id - VLAN id to look for
+- *  @param protocol - either AF_INET or AF_INET6
+- *  @return nic_iface - if found network interface with the given VLAN ID
+- *                      if not found a NULL is returned
+- */
+-nic_interface_t *nic_find_vlan_iface_protocol(nic_t *nic,
+-					      nic_interface_t *nic_iface,
+-					      uint16_t vlan_id,
+-					      uint16_t protocol)
+-{
+-	nic_interface_t *current;
+-
+-	pthread_mutex_lock(&nic->nic_mutex);
+-
+-	current = nic_iface->vlan_next;
+-	while (current != NULL) {
+-		if ((current->vlan_id == vlan_id) &&
+-		    (current->protocol == protocol)) {
+-			pthread_mutex_unlock(&nic->nic_mutex);
+-			return current;
+-		}
+-		current = current->vlan_next;
+-	}
+-
+-	pthread_mutex_unlock(&nic->nic_mutex);
+-	return NULL;
+ }
+ 
++/* Sets the nic_iface to the front of the AF */
+ void set_nic_iface(nic_t *nic, nic_interface_t *nic_iface)
+ {
+ 	nic_interface_t *current, *prev;
++	nic_interface_t *current_vlan, *prev_vlan;
+ 
+-	pthread_mutex_lock(&nic->nic_mutex);
+-
+-	if (nic->nic_iface == nic_iface)
+-		goto done;
+-
+-	prev = nic->nic_iface;
+-	current = nic->nic_iface->next;
++	prev = NULL;
++	current = nic->nic_iface;
+ 	while (current != NULL) {
+-		if (current == nic_iface) {
+-			prev->next = current->next;
+-			current->next = nic->nic_iface;
+-			nic->nic_iface = current;
++		if (current->protocol != nic_iface->protocol)
++			goto next;
++		/* If its already on top of the list, exit */
++		if (current == nic_iface)
+ 			goto done;
++
++		prev_vlan = current;
++		current_vlan = current->vlan_next;
++
++		while (current_vlan != NULL) {
++			if (current_vlan == nic_iface) {
++				/* Found inside the vlan list */
++				/* For vlan == 0, place on top of
++				   the AF list */
++				prev_vlan->vlan_next =
++						current_vlan->vlan_next;
++				current_vlan->vlan_next = current;
++				if (prev)
++					prev->next = current_vlan;
++				else
++					nic->nic_iface = current_vlan;
++				goto done;
++			}
++			prev_vlan = current_vlan;
++			current_vlan = current_vlan->vlan_next;
+ 		}
++next:
+ 		prev = current;
+ 		current = current->next;
+ 	}
+ done:
+-	pthread_mutex_unlock(&nic->nic_mutex);
++	return;
+ }
++
+ /*******************************************************************************
+  *  Packet management utility functions
+  ******************************************************************************/
+@@ -1639,7 +1612,7 @@ int capture_file(char **raw, uint32_t * raw_size, const char *path)
+ 	}
+ 
+ 	read_size = fread(*raw, file_size, 1, fp);
+-	if (read_size < 0) {
++	if (!read_size) {
+ 		LOG_ERR("Could not read capture, path: %s len: %d [%s]",
+ 			path, file_size, strerror(ferror(fp)));
+ 		free(*raw);
+diff --git a/src/unix/nic_utils.h b/src/unix/nic_utils.h
+index ff76f6b..6c57701 100644
+--- a/src/unix/nic_utils.h
++++ b/src/unix/nic_utils.h
+@@ -67,7 +67,9 @@ void nic_fill_ethernet_header(nic_interface_t * nic_iface,
+ 			      int *pkt_size, void **start_addr,
+ 			      uint16_t ether_type);
+ 
+-nic_interface_t *nic_find_nic_iface(nic_t * nic, uint16_t vlan_id);
++struct nic_interface *nic_find_nic_iface(nic_t *nic, uint16_t protocol,
++					 uint16_t vlan_id, int iface_num,
++					 int request_type);
+ void set_nic_iface(nic_t *nic, nic_interface_t *nic_iface);
+ 
+ void persist_all_nic_iface(nic_t * nic);
+diff --git a/src/unix/nic_vlan.c b/src/unix/nic_vlan.c
+index 4f8f551..90a6244 100644
+--- a/src/unix/nic_vlan.c
++++ b/src/unix/nic_vlan.c
+@@ -332,7 +332,8 @@ int find_vlans_using_phy_interface(struct vlan_handle *handle,
+  */
+ int valid_vlan(short int vlan)
+ {
+-	if (vlan > 1 && vlan < 4095)
++	/* Allow vlan 1 to connect */
++	if (vlan > 0 && vlan < 4095)
+ 		return 1;
+ 
+ 	return 0;
+diff --git a/src/unix/packet.c b/src/unix/packet.c
+index 4d8bf55..5047030 100644
+--- a/src/unix/packet.c
++++ b/src/unix/packet.c
+@@ -88,7 +88,7 @@ void free_packet(struct packet *pkt)
+  *  reset_packet() - This will reset the packet fields to default values
+  *  @param pkt - the packet to reset
+  */
+-void reset_packet(packet_t * pkt)
++void reset_packet(packet_t *pkt)
+ {
+ 	pkt->next = NULL;
+ 
+@@ -101,7 +101,7 @@ void reset_packet(packet_t * pkt)
+ 	pkt->network_layer = NULL;
+ }
+ 
+-int alloc_free_queue(nic_t * nic, size_t num_of_packets)
++int alloc_free_queue(nic_t *nic, size_t num_of_packets)
+ {
+ 	int rc, i;
+ 
+-- 
+1.7.11.7
+
diff --git a/0072-iscsiuio-0.7.6.1.patch b/0072-iscsiuio-0.7.6.1.patch
new file mode 100644
index 0000000..595d0e2
--- /dev/null
+++ b/0072-iscsiuio-0.7.6.1.patch
@@ -0,0 +1,326 @@
+From 057e4ade3814e3ae41a4226c63e76cc36c8147bf Mon Sep 17 00:00:00 2001
+From: Chris Leech <cleech at redhat.com>
+Date: Wed, 19 Dec 2012 21:28:18 -0800
+Subject: iscsiuio 0.7.6.1
+
+---
+ README                |  4 ++--
+ RELEASE.TXT           | 34 ++++++++++++++++++++++++++++++++--
+ configure             | 18 +++++++++---------
+ configure.ac          |  4 ++--
+ docs/iscsiuio.8       |  4 ++--
+ src/uip/uip_arp.c     |  1 -
+ src/unix/libs/bnx2x.c | 19 ++++++++++++++++---
+ src/unix/libs/bnx2x.h |  8 +++++++-
+ src/unix/nic.c        |  3 ++-
+ src/unix/nic_nl.c     |  2 +-
+ 10 files changed, 73 insertions(+), 24 deletions(-)
+
+diff --git a/README b/README
+index a716263..e5ee23f 100644
+--- a/README
++++ b/README
+@@ -1,6 +1,6 @@
+ iscsiuio Userspace Tool
+-Version 0.7.4.3
+-Aug 16, 2012
++Version 0.7.6.1
++Oct 09, 2012
+ ------------------------------------------------------
+ 
+ This tool is to be used in conjunction with the Broadcom NetXtreme II Linux
+diff --git a/RELEASE.TXT b/RELEASE.TXT
+index cb1d470..0e7665c 100644
+--- a/RELEASE.TXT
++++ b/RELEASE.TXT
+@@ -1,7 +1,7 @@
+                               Release Notes
+                         Broadcom uIP Linux Driver
+-                            Version 0.7.4.3
+-                               08/16/2012
++                            Version 0.7.6.1
++                               10/15/2012
+ 
+                           Broadcom Corporation
+                          5300 California Avenue,
+@@ -11,6 +11,36 @@
+                            All rights reserved
+ 
+ 
++uIP v0.7.6.1 (Oct 15, 2012)
++=======================================================
++   Fixes
++   -----
++   1. Problem: Cont00065690 - Vconfig method of connecting over
++               tagged vlan with IPv6 failed
++      Cause:   The new net param support changes has prevented
++               the old vconfig method from execising the IPv6
++               acquisition engine properly
++      Change:  Ensure that this old vconfig method to run the IPv6
++               acquisition engine properly and to its entirety
++      Impact:  IPv6 + VLAN using the network VLAN configuration
++               method
++
++   2. Problem: Cont00065768 - RHEL5.X iscsiuio segfault possible
++               if there is a specific 1024 byte size broadcast
++               packet
++      Cause:   This is a corner case where the packet size is
++               exactly 1024 bytes + padding that exceeded the
++               DMA rx buffer.  This has been there since day 1.
++      Change:  Ensure that the packet size + padding do not
++               exceed this limit.
++      Impact:  10G only.  1G already has the guard against it.
++
++   Enhancements
++   ------------
++   1. Change:  Added support for 10G 57840 4x10 and 2x20
++      Impact:  10G 57840
++
++
+ uIP v0.7.4.3 (Aug 16, 2012)
+ =======================================================
+    Fixes
+diff --git a/configure b/configure
+index 6ff2e68..0b2abc4 100755
+--- a/configure
++++ b/configure
+@@ -1,6 +1,6 @@
+ #! /bin/sh
+ # Guess values for system-dependent variables and create Makefiles.
+-# Generated by GNU Autoconf 2.59 for iscsiuio 0.7.4.3.
++# Generated by GNU Autoconf 2.59 for iscsiuio 0.7.6.1.
+ #
+ # Report bugs to <eddie.wai at broadcom.com>.
+ #
+@@ -423,8 +423,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
+ # Identity of this package.
+ PACKAGE_NAME='iscsiuio'
+ PACKAGE_TARNAME='iscsiuio'
+-PACKAGE_VERSION='0.7.4.3'
+-PACKAGE_STRING='iscsiuio 0.7.4.3'
++PACKAGE_VERSION='0.7.6.1'
++PACKAGE_STRING='iscsiuio 0.7.6.1'
+ PACKAGE_BUGREPORT='eddie.wai at broadcom.com'
+ 
+ # Factoring default headers for most tests.
+@@ -954,7 +954,7 @@ if test "$ac_init_help" = "long"; then
+   # Omit some internal or obsolete options to make the list less imposing.
+   # This message is too long to be a string in the A/UX 3.1 sh.
+   cat <<_ACEOF
+-\`configure' configures iscsiuio 0.7.4.3 to adapt to many kinds of systems.
++\`configure' configures iscsiuio 0.7.6.1 to adapt to many kinds of systems.
+ 
+ Usage: $0 [OPTION]... [VAR=VALUE]...
+ 
+@@ -1020,7 +1020,7 @@ fi
+ 
+ if test -n "$ac_init_help"; then
+   case $ac_init_help in
+-     short | recursive ) echo "Configuration of iscsiuio 0.7.4.3:";;
++     short | recursive ) echo "Configuration of iscsiuio 0.7.6.1:";;
+    esac
+   cat <<\_ACEOF
+ 
+@@ -1161,7 +1161,7 @@ fi
+ test -n "$ac_init_help" && exit 0
+ if $ac_init_version; then
+   cat <<\_ACEOF
+-iscsiuio configure 0.7.4.3
++iscsiuio configure 0.7.6.1
+ generated by GNU Autoconf 2.59
+ 
+ Copyright (C) 2003 Free Software Foundation, Inc.
+@@ -1175,7 +1175,7 @@ cat >&5 <<_ACEOF
+ This file contains any messages produced by compilers while
+ running configure, to aid debugging if configure makes a mistake.
+ 
+-It was created by iscsiuio $as_me 0.7.4.3, which was
++It was created by iscsiuio $as_me 0.7.6.1, which was
+ generated by GNU Autoconf 2.59.  Invocation command line was
+ 
+   $ $0 $@
+@@ -21726,7 +21726,7 @@ _ASBOX
+ } >&5
+ cat >&5 <<_CSEOF
+ 
+-This file was extended by iscsiuio $as_me 0.7.4.3, which was
++This file was extended by iscsiuio $as_me 0.7.6.1, which was
+ generated by GNU Autoconf 2.59.  Invocation command line was
+ 
+   CONFIG_FILES    = $CONFIG_FILES
+@@ -21789,7 +21789,7 @@ _ACEOF
+ 
+ cat >>$CONFIG_STATUS <<_ACEOF
+ ac_cs_version="\\
+-iscsiuio config.status 0.7.4.3
++iscsiuio config.status 0.7.6.1
+ configured by $0, generated by GNU Autoconf 2.59,
+   with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
+ 
+diff --git a/configure.ac b/configure.ac
+index 0b1e7f1..1045a80 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -11,9 +11,9 @@ dnl Maintained by: Eddie Wai (eddie.wai at broadcom.com)
+ dnl
+ 
+ PACKAGE=iscsiuio
+-VERSION=0.7.4.3
++VERSION=0.7.6.1
+ 
+-AC_INIT(iscsiuio, 0.7.4.3, eddie.wai at broadcom.com)
++AC_INIT(iscsiuio, 0.7.6.1, eddie.wai at broadcom.com)
+ 
+ AM_INIT_AUTOMAKE($PACKAGE, $VERSION)
+ AC_CONFIG_HEADER(config.h)
+diff --git a/docs/iscsiuio.8 b/docs/iscsiuio.8
+index 4bf26df..d107327 100644
+--- a/docs/iscsiuio.8
++++ b/docs/iscsiuio.8
+@@ -3,9 +3,9 @@
+ .\" modify it under the terms of the GNU General Public License as
+ .\" published by the Free Software Foundation.
+ .\"
+-.\" bnx2.4,v 0.7.4.3
++.\" bnx2.4,v 0.7.6.1
+ .\"
+-.TH iscsiuio 8 "08/16/2012" "Broadcom Corporation"
++.TH iscsiuio 8 "10/09/2012" "Broadcom Corporation"
+ .\"
+ .\" NAME part
+ .\"
+diff --git a/src/uip/uip_arp.c b/src/uip/uip_arp.c
+index 3ef3b07..9dd02a1 100644
+--- a/src/uip/uip_arp.c
++++ b/src/uip/uip_arp.c
+@@ -273,7 +273,6 @@ uip_arp_arpin(nic_interface_t * nic_iface,
+ 				pkt->buf_size = sizeof(*arp) +
+ 						sizeof(struct uip_vlan_eth_hdr);
+ 			}
+-			pkt->buf_size = sizeof(*arp) + sizeof(*eth);
+ 		}
+ 		break;
+ 	case const_htons(ARP_REPLY):
+diff --git a/src/unix/libs/bnx2x.c b/src/unix/libs/bnx2x.c
+index 5e33420..70e85c0 100644
+--- a/src/unix/libs/bnx2x.c
++++ b/src/unix/libs/bnx2x.c
+@@ -103,6 +103,10 @@ static const char brcm_57840_MF[] = "Broadcom NetXtreme II BCM57840 MF "
+ 				    "10-Gigabit";
+ static const char brcm_57840_VF[] = "Broadcom NetXtreme II BCM57840 VF "
+ 				    "10-Gigabit";
++static const char brcm_57840_4_10[] = "Broadcom NetXtreme II BCM57840 4x"
++				      "10-Gigabit";
++static const char brcm_57840_2_20[] = "Broadcom NetXtreme II BCM57840 2x"
++				      "20-Gigabit";
+ 
+ /*******************************************************************************
+  * PCI ID constants
+@@ -123,6 +127,8 @@ static const char brcm_57840_VF[] = "Broadcom NetXtreme II BCM57840 VF "
+ #define PCI_DEVICE_ID_NX2_57840		0x168d
+ #define PCI_DEVICE_ID_NX2_57840_MF	0x16ab
+ #define PCI_DEVICE_ID_NX2_57840_VF	0x16ad
++#define PCI_DEVICE_ID_NX2_57840_4_10	0x16a1
++#define PCI_DEVICE_ID_NX2_57840_2_20	0x16a2
+ #define PCI_ANY_ID (~0)
+ 
+ /*  This is the table used to match PCI vendor and device ID's to the
+@@ -158,6 +164,10 @@ static const struct pci_device_id bnx2x_pci_tbl[] = {
+ 	 PCI_ANY_ID, PCI_ANY_ID, brcm_57840_MF},
+ 	{PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_57840_VF,
+ 	 PCI_ANY_ID, PCI_ANY_ID, brcm_57840_VF},
++	{PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_57840_4_10,
++	 PCI_ANY_ID, PCI_ANY_ID, brcm_57840_4_10},
++	{PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_57840_2_20,
++	 PCI_ANY_ID, PCI_ANY_ID, brcm_57840_2_20},
+ };
+ 
+ static struct iro e1_iro[2] = {
+@@ -1401,7 +1411,7 @@ static int bnx2x_read(nic_t * nic, packet_t * pkt)
+ 		union eth_rx_cqe *cqe;
+ 		__u8 cqe_fp_flags;
+ 		void *rx_pkt;
+-		int len, pad, cqe_size;
++		int len, pad, cqe_size, max_len;
+ 		rc = 1;
+ 
+ 		if (bnx2x_is_ver70(bp)) {
+@@ -1427,10 +1437,13 @@ static int bnx2x_read(nic_t * nic, packet_t * pkt)
+ 
+ 			/*  Doto query MTU size of physical device */
+ 			/*  Ensure len is valid */
+-			if (len > pkt->max_buf_size)
++			max_len = pkt->max_buf_size < bp->rx_buffer_size ?
++				  pkt->max_buf_size : bp->rx_buffer_size;
++			if (len > max_len) {
+ 				LOG_DEBUG(PFX "%s: bad BD length: %d",
+ 					  nic->log_name, len);
+-
++				len = max_len;
++			}
+ 			if (len > 0) {
+ 				msync(rx_pkt, len, MS_SYNC);
+ 				/*  Copy the data */
+diff --git a/src/unix/libs/bnx2x.h b/src/unix/libs/bnx2x.h
+index b758179..1f47011 100644
+--- a/src/unix/libs/bnx2x.h
++++ b/src/unix/libs/bnx2x.h
+@@ -430,6 +430,8 @@ struct client_init_general_data {
+ #define CHIP_NUM_57800			0x168a
+ #define CHIP_NUM_57810			0x168e
+ #define CHIP_NUM_57840			0x168d
++#define CHIP_NUM_57840_4_10		0x16a1
++#define CHIP_NUM_57840_2_20		0x16a2
+ 
+ #define CHIP_IS_E1(bp)			(BNX2X_CHIP_NUM(bp) == CHIP_NUM_57710)
+ #define CHIP_IS_57711(bp)		(BNX2X_CHIP_NUM(bp) == CHIP_NUM_57711)
+@@ -438,7 +440,11 @@ struct client_init_general_data {
+ #define CHIP_IS_57712E(bp)		(BNX2X_CHIP_NUM(bp) == CHIP_NUM_57712E)
+ #define CHIP_IS_57800(bp)		(BNX2X_CHIP_NUM(bp) == CHIP_NUM_57800)
+ #define CHIP_IS_57810(bp)		(BNX2X_CHIP_NUM(bp) == CHIP_NUM_57810)
+-#define CHIP_IS_57840(bp)		(BNX2X_CHIP_NUM(bp) == CHIP_NUM_57840)
++#define CHIP_IS_57840_4_10(bp)		(BNX2X_CHIP_NUM(bp) == CHIP_NUM_57840_4_10)
++#define CHIP_IS_57840_2_20(bp)		(BNX2X_CHIP_NUM(bp) == CHIP_NUM_57840_2_20)
++#define CHIP_IS_57840(bp)		(BNX2X_CHIP_NUM(bp) == CHIP_NUM_57840 || \
++					 CHIP_IS_57840_4_10(bp) || \
++					 CHIP_IS_57840_2_20(bp))
+ #define CHIP_IS_E1H(bp)			(CHIP_IS_57711(bp) || \
+ 					 CHIP_IS_57711E(bp))
+ #define CHIP_IS_E2(bp)			(CHIP_IS_57712(bp) || \
+diff --git a/src/unix/nic.c b/src/unix/nic.c
+index 0b3c538..72afff0 100644
+--- a/src/unix/nic.c
++++ b/src/unix/nic.c
+@@ -460,6 +460,7 @@ int nic_remove(nic_t * nic)
+ 	rc = stat(nic->uio_device_name, &file_stat);
+ 	if ((rc == 0) && (nic->ops))
+ 		nic->ops->close(nic, 0);
++	pthread_mutex_unlock(&nic->nic_mutex);
+ 
+ 	nic->state = NIC_EXIT;
+ 
+@@ -910,7 +911,7 @@ int do_timers_per_nic_iface(nic_t *nic, nic_interface_t *nic_iface,
+ 	if (pkt == NULL)
+ 		return -EIO;
+ 
+-	if (nic_iface->ustack.ip_config == AF_INET) {
++	if (nic_iface->protocol == AF_INET) {
+ 		for (i = 0; i < UIP_UDP_CONNS; i++) {
+ 			prepare_ustack(nic, nic_iface, ustack, pkt);
+ 
+diff --git a/src/unix/nic_nl.c b/src/unix/nic_nl.c
+index 34e2062..8afd9ae 100644
+--- a/src/unix/nic_nl.c
++++ b/src/unix/nic_nl.c
+@@ -408,7 +408,7 @@ static int ctldev_handle(char *data, nic_t *nic)
+ 			persist_all_nic_iface(nic);
+ 
+ 			nic_iface = vlan_iface;
+-
++			nic_iface->flags |= NIC_IFACE_ACQUIRE;
+ 			pthread_mutex_unlock(&nic->nic_mutex);
+ 
+ 			/* nic_disable but not going down */
+-- 
+1.7.11.7
+
diff --git a/0099-use-Red-Hat-version-string-to-match-RPM-package-vers.patch b/0099-use-Red-Hat-version-string-to-match-RPM-package-vers.patch
new file mode 100644
index 0000000..17718c0
--- /dev/null
+++ b/0099-use-Red-Hat-version-string-to-match-RPM-package-vers.patch
@@ -0,0 +1,25 @@
+From 2c05e5731fdbe21c3a44f9c62963a838bf74ec5b Mon Sep 17 00:00:00 2001
+From: Chris Leech <cleech at redhat.com>
+Date: Mon, 21 Jan 2013 15:43:36 -0800
+Subject: use Red Hat version string to match RPM package version
+
+---
+ usr/version.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/usr/version.h b/usr/version.h
+index a090522..aef0c3d 100644
+--- a/usr/version.h
++++ b/usr/version.h
+@@ -6,7 +6,7 @@
+  * This may not be the same value as the kernel versions because
+  * some other maintainer could merge a patch without going through us
+  */
+-#define ISCSI_VERSION_STR	"2.0-873"
++#define ISCSI_VERSION_STR	"6.2.0.873-1"
+ #define ISCSI_VERSION_FILE	"/sys/module/scsi_transport_iscsi/version"
+ 
+ #endif
+-- 
+1.7.11.7
+
diff --git a/iscsi-initiator-utils.spec b/iscsi-initiator-utils.spec
index 3cb86be..dc4f3a6 100644
--- a/iscsi-initiator-utils.spec
+++ b/iscsi-initiator-utils.spec
@@ -1,51 +1,43 @@
 %{!?python_sitearch: %global python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)")}
 
+%define open_iscsi_version	2.0
+%define open_iscsi_build	873
+%define iscsiuio_version	0.7.2.1
+
 Summary: iSCSI daemon and utility programs
 Name: iscsi-initiator-utils
-Version: 6.2.0.872
-Release: 19%{?dist}
-Source0: http://people.redhat.com/mchristi/iscsi/rhel6.0/source/open-iscsi-2.0-872-rc4-bnx2i.tar.gz
-Source1: iscsid.init
-Source2: iscsidevs.init
-Source3: 04-iscsi
-# sync brcm to 0.7.0.12
-Patch0: iscsi-initiator-utils-sync-uio-0.7.0.8.patch
-# sync iscsi tools to upstream commit e8c5b1d34ee5ce0a755ff54518829156dfa5fabe 
-Patch1: iscsi-initiator-utils-sync-iscsi.patch
-# Add Red Hat specific info to docs.
-Patch2: iscsi-initiator-utils-update-initscripts-and-docs.patch
-# Upstream uses /etc/iscsi for iscsi db info, but use /var/lib/iscsi.
-Patch3: iscsi-initiator-utils-use-var-for-config.patch
-# Add redhat.com string to default initiator name.
-Patch4: iscsi-initiator-utils-use-red-hat-for-name.patch
-# Add a lib for use by anaconda.
-Patch5: iscsi-initiator-utils-add-libiscsi.patch
-# Add bnx2i support.
-Patch6: iscsi-initiator-utils-uip-mgmt.patch
-# Don't compile iscsistart as static
-Patch7: iscsi-initiator-utils-dont-use-static.patch
-# Remove the OFFLOAD_BOOT_SUPPORTED #ifdef.
-Patch8: iscsi-initiator-utils-remove-the-offload-boot-supported-ifdef.patch
-# brcm uio: handle the different iface_rec structures in iscsid and brcm. 
-Patch9: iscsi-initiator-utils-uio-handle-different-iface_rec.patch
-# Document missing brcm arguments
-Patch10: iscsi-initiator-utils-brcm-man.patch
-# setup default ifaces for all ifaces in kernel
-Patch11: iscsi-initiator-utils-fix-default-bindings.patch
-# fix iscsiadm return value/msg when login fails
-Patch12: iscsi-initiator-utils-fix-iscsiadm-return.patch
-# don't use openssl-devel
-Patch13: iscsi-initiator-utils-dont-use-openssl.patch
-# sync uio to 0.7.0.14
-Patch14: iscsi-initiator-utils-sync-uio-0.7.0.14.patch
-# fix nl msglen
-Patch15: iscsi-initiator-utils-fix-nlmsglen.patch
-# fixes for offload iface support
-Patch16: iscsi-initiator-utils-ofl-iface-fixes.patch
-# fix ipv6 ibft/firmware boot
-Patch17: iscsi-initiator-utils-fix-ipv6-boot.patch
-# add rhel version info to iscsi tools
-Patch18: iscsi-initiator-utils-add-rh-ver.patch
+Version: 6.%{open_iscsi_version}.%{open_iscsi_build}
+Release: 1%{?dist}
+Source0: http://www.open-iscsi.org/bits/open-iscsi-%{open_iscsi_version}-%{open_iscsi_build}.tar.gz
+Source1: iscsiuio-%{iscsiuio_version}.tar.gz
+Source2: iscsid.init
+Source3: iscsidevs.init
+Source4: 04-iscsi
+
+# upstream patches, post last tagged version
+Patch1: 0001-iscsid-fix-iscsid-segfault-during-qla4xxx-login.patch
+Patch2: 0002-ISCSISTART-Bring-up-the-corresponding-network-interf.patch
+Patch3: 0003-iscsi-tools-fix-compile-error-when-OFFLOAD_BOOT_SUPP.patch
+Patch4: 0004-ISCSID-Passing-more-net-params-from-ibft-to-iface.patch
+Patch5: 0005-iscsi-tools-Convert-r-argument-to-an-integer-before-.patch
+Patch6: 0006-Update-README-for-removal-of-DBM-requirement.patch
+Patch7: 0007-iscsid-iscsiadm-fix-abstract-socket-length-in-bind-c.patch
+Patch8: 0008-iscsid-implement-systemd-compatible-socket-activatio.patch
+Patch9: 0009-iscsid-add-example-unit-files-for-systemd.patch
+Patch10: 0010-iscsi-tools-fix-get_random_bytes-error-handling.patch
+# distro specific modifications
+Patch51: 0051-update-initscripts-and-docs.patch
+Patch52: 0052-use-var-for-config.patch
+Patch53: 0053-use-red-hat-for-name.patch
+Patch54: 0054-add-libiscsi.patch
+Patch55: 0055-dont-use-static.patch
+Patch56: 0056-remove-the-offload-boot-supported-ifdef.patch
+Patch57: 0057-iscsid-iscsiuio-ipc-interface.patch
+# iscsiuio patches
+Patch71: 0071-iscsiuio-0.7.4.3.patch
+Patch72: 0072-iscsiuio-0.7.6.1.patch
+# version string, needs to be updated with each build
+Patch99: 0099-use-Red-Hat-version-string-to-match-RPM-package-vers.patch
 
 
 Group: System Environment/Daemons
@@ -74,26 +66,35 @@ The %{name}-devel package contains libraries and header files for
 developing applications that use %{name}.
 
 %prep
-%setup -q -n open-iscsi-2.0-872-rc4-bnx2i
-%patch0 -p1 -b .sync-uio-0.7.0.8
-%patch1 -p1 -b .sync-iscsi
-%patch2 -p1 -b .update-initscripts-and-docs
-%patch3 -p1 -b .use-var-for-config
-%patch4 -p1 -b .use-red-hat-for-name
-%patch5 -p1 -b .add-libiscsi
-%patch6 -p1 -b .uip-mgmt
-%patch7 -p1 -b .dont-use-static
-%patch8 -p1 -b .remove-the-offload-boot-supported-ifdef
-%patch9 -p1 -b .uio-handle-different-iface_rec
-%patch10 -p1 -b .brcm-man
-%patch11 -p1 -b .fix-default-bindings
-%patch12 -p1 -b .fix-iscsiadm-return
-%patch13 -p1 -b .dont-use-openssl
-%patch14 -p1 -b .sync-uio-0.7.0.14
-%patch15 -p1 -b .fix-nlmsglen
-%patch16 -p1 -b .ofl-iface-fixes
-%patch17 -p1 -b .fix-ipv6-boot
-%patch18 -p1 -b .add-rh-ver
+%setup -q -n open-iscsi-%{open_iscsi_version}-%{open_iscsi_build} -a 1
+mv iscsiuio-%{iscsiuio_version} iscsiuio
+# upstream patches
+%patch1 -p1
+%patch2 -p1
+%patch3 -p1
+%patch4 -p1
+%patch5 -p1
+%patch6 -p1
+%patch7 -p1
+%patch8 -p1
+%patch9 -p1
+%patch10 -p1
+# distro specific modifications
+%patch51 -p1
+%patch52 -p1
+%patch53 -p1
+%patch54 -p1
+%patch55 -p1
+%patch56 -p1
+%patch57 -p1
+# iscsiuio patches
+cd iscsiuio
+%patch71 -p1
+%patch72 -p1
+cd ..
+# version string
+%patch99 -p1
+
 
 %build
 cd utils/open-isns
@@ -150,9 +151,9 @@ install -p -m 644 iscsiuio/docs/iscsiuio.8 $RPM_BUILD_ROOT/%{_mandir}/man8
 install -p -m 644 iscsiuio/iscsiuiolog $RPM_BUILD_ROOT%{_sysconfdir}/logrotate.d
 install -p -m 755 iscsiuio/src/unix/iscsiuio $RPM_BUILD_ROOT/sbin
 
-install -p -m 755 %{SOURCE1} $RPM_BUILD_ROOT%{_initrddir}/iscsid
-install -p -m 755 %{SOURCE2} $RPM_BUILD_ROOT%{_initrddir}/iscsi
-install -p -m 755 %{SOURCE3} $RPM_BUILD_ROOT/etc/NetworkManager/dispatcher.d
+install -p -m 755 %{SOURCE2} $RPM_BUILD_ROOT%{_initrddir}/iscsid
+install -p -m 755 %{SOURCE3} $RPM_BUILD_ROOT%{_initrddir}/iscsi
+install -p -m 755 %{SOURCE4} $RPM_BUILD_ROOT/etc/NetworkManager/dispatcher.d
 
 install -p -m 755 libiscsi/libiscsi.so.0 $RPM_BUILD_ROOT%{_libdir}
 ln -s libiscsi.so.0 $RPM_BUILD_ROOT%{_libdir}/libiscsi.so
diff --git a/sources b/sources
index a1945c6..ef715a6 100644
--- a/sources
+++ b/sources
@@ -1 +1,2 @@
-fdc3d1fd718a6f5e4281db84c993a5e2  open-iscsi-2.0-872-rc4-bnx2i.tar.gz
+8b8316d7c9469149a6cc6234478347f7  open-iscsi-2.0-873.tar.gz
+22e8862a1aee0f3565b9caa4e22995f4  iscsiuio-0.7.2.1.tar.gz


More information about the scm-commits mailing list