5ebdd5
diff --git a/usr/Makefile b/usr/Makefile
5ebdd5
index e9d6bd1..8e505bf 100644
5ebdd5
--- a/usr/Makefile
5ebdd5
+++ b/usr/Makefile
5ebdd5
@@ -42,7 +42,7 @@ ISCSI_LIB_SRCS = iscsi_util.o io.o auth.o login.o log.o md5.o sha1.o iface.o \
5ebdd5
 	iscsid_req.o $(SYSDEPS_SRCS)
5ebdd5
 # core initiator files
5ebdd5
 INITIATOR_SRCS = initiator.o scsi.o actor.o event_poll.o mgmt_ipc.o \
5ebdd5
-		transport.o cxgb3i.o be2iscsi.o
5ebdd5
+		transport.o cxgb3i.o be2iscsi.o uip_mgmt_ipc.o
5ebdd5
 # fw boot files
5ebdd5
 FW_BOOT_SRCS = $(wildcard ../utils/fwparam_ibft/*.o)
5ebdd5
 
5ebdd5
diff --git a/usr/initiator.c b/usr/initiator.c
5ebdd5
index 1c9d8b6..8f7a383 100644
5ebdd5
--- a/usr/initiator.c
5ebdd5
+++ b/usr/initiator.c
5ebdd5
@@ -45,6 +45,7 @@
5ebdd5
 #include "iscsi_sysfs.h"
5ebdd5
 #include "iscsi_settings.h"
5ebdd5
 #include "iface.h"
5ebdd5
+#include "host.h"
5ebdd5
 #include "sysdeps.h"
5ebdd5
 
5ebdd5
 #define ISCSI_CONN_ERR_REOPEN_DELAY	3
5ebdd5
@@ -743,6 +744,38 @@ static int iscsi_conn_connect(struct iscsi_conn *conn, queue_task_t *qtask)
5ebdd5
 	return 0;
5ebdd5
 }
5ebdd5
 
5ebdd5
+static int __set_net_config(struct iscsi_transport *t,
5ebdd5
+			    iscsi_session_t *session,
5ebdd5
+			    struct iface_rec *iface)
5ebdd5
+{
5ebdd5
+	if (t->template->set_net_config) {
5ebdd5
+		/* uip needs the netdev name */
5ebdd5
+		struct host_info hinfo;
5ebdd5
+		int hostno, rc;
5ebdd5
+
5ebdd5
+		/* this assumes that the netdev or hw address is going to be
5ebdd5
+		   set */
5ebdd5
+		hostno = iscsi_sysfs_get_host_no_from_hwinfo(iface, &rc);
5ebdd5
+		if (rc) {
5ebdd5
+			log_debug(4, "Couldn't get host no.\n");
5ebdd5
+			return rc;
5ebdd5
+		}
5ebdd5
+
5ebdd5
+		/* uip needs the netdev name */
5ebdd5
+		if (!strlen(iface->netdev)) {
5ebdd5
+			memset(&hinfo, 0, sizeof(hinfo));
5ebdd5
+			hinfo.host_no = hostno;
5ebdd5
+			iscsi_sysfs_get_hostinfo_by_host_no(&hinfo);
5ebdd5
+			strcpy(iface->netdev, hinfo.iface.netdev);
5ebdd5
+		}
5ebdd5
+
5ebdd5
+		return t->template->set_net_config(t, iface, session);
5ebdd5
+	}
5ebdd5
+
5ebdd5
+	return 0;
5ebdd5
+}
5ebdd5
+
5ebdd5
+
5ebdd5
 static void
5ebdd5
 __session_conn_reopen(iscsi_conn_t *conn, queue_task_t *qtask, int do_stop,
5ebdd5
 		      int redirected)
5ebdd5
@@ -784,6 +817,11 @@ __session_conn_reopen(iscsi_conn_t *conn, queue_task_t *qtask, int do_stop,
5ebdd5
 	if (!redirected)
5ebdd5
 		session->reopen_cnt++;
5ebdd5
 
5ebdd5
+	/* uIP will needs to be re-triggered on the connection re-open */
5ebdd5
+	if (__set_net_config(conn->session->t, conn->session,
5ebdd5
+			      &conn->session->nrec.iface) != 0)
5ebdd5
+		goto queue_reopen;
5ebdd5
+
5ebdd5
 	if (iscsi_conn_connect(conn, qtask)) {
5ebdd5
 		delay = ISCSI_CONN_ERR_REOPEN_DELAY;
5ebdd5
 		goto queue_reopen;
5ebdd5
@@ -2130,6 +2168,10 @@ static int iface_set_param(struct iscsi_transport *t, struct iface_rec *iface,
5ebdd5
 		return EINVAL;
5ebdd5
 	}
5ebdd5
 
5ebdd5
+	rc = __set_net_config(t, session, iface);
5ebdd5
+	if (rc != 0)
5ebdd5
+		return rc;
5ebdd5
+
5ebdd5
 	rc = __iscsi_host_set_param(t, session->hostno,
5ebdd5
 				    ISCSI_HOST_PARAM_IPADDRESS,
5ebdd5
 				    iface->ipaddress, ISCSI_STRING);
5ebdd5
diff --git a/usr/iscsid_req.c b/usr/iscsid_req.c
5ebdd5
index 5280a0a..6eb8b1d 100644
5ebdd5
--- a/usr/iscsid_req.c
5ebdd5
+++ b/usr/iscsid_req.c
5ebdd5
@@ -22,6 +22,7 @@
5ebdd5
 #include <stdlib.h>
5ebdd5
 #include <string.h>
5ebdd5
 #include <errno.h>
5ebdd5
+#include <fcntl.h>
5ebdd5
 #include <sys un.h="">
5ebdd5
 #include <sys types.h="">
5ebdd5
 #include <sys socket.h="">
5ebdd5
@@ -31,6 +32,7 @@
5ebdd5
 #include "mgmt_ipc.h"
5ebdd5
 #include "iscsi_util.h"
5ebdd5
 #include "config.h"
5ebdd5
+#include "uip_mgmt_ipc.h"
5ebdd5
 
5ebdd5
 static void iscsid_startup(void)
5ebdd5
 {
5ebdd5
@@ -51,7 +53,8 @@ static void iscsid_startup(void)
5ebdd5
 
5ebdd5
 #define MAXSLEEP 128
5ebdd5
 
5ebdd5
-static mgmt_ipc_err_e iscsid_connect(int *fd, int start_iscsid)
5ebdd5
+static mgmt_ipc_err_e ipc_connect(int *fd, char *unix_sock_name,
5ebdd5
+				  int start_iscsid)
5ebdd5
 {
5ebdd5
 	int nsec;
5ebdd5
 	struct sockaddr_un addr;
5ebdd5
@@ -64,8 +67,8 @@ static mgmt_ipc_err_e iscsid_connect(int *fd, int start_iscsid)
5ebdd5
 
5ebdd5
 	memset(&addr, 0, sizeof(addr));
5ebdd5
 	addr.sun_family = AF_LOCAL;
5ebdd5
-	memcpy((char *) &addr.sun_path + 1, ISCSIADM_NAMESPACE,
5ebdd5
-		strlen(ISCSIADM_NAMESPACE));
5ebdd5
+	memcpy((char *) &addr.sun_path + 1, unix_sock_name,
5ebdd5
+		strlen(unix_sock_name));
5ebdd5
 	/*
5ebdd5
 	 * Trying to connect with exponential backoff
5ebdd5
 	 */
5ebdd5
@@ -93,6 +96,11 @@ static mgmt_ipc_err_e iscsid_connect(int *fd, int start_iscsid)
5ebdd5
 	return MGMT_IPC_ERR_ISCSID_NOTCONN;
5ebdd5
 }
5ebdd5
 
5ebdd5
+static mgmt_ipc_err_e iscsid_connect(int *fd, int start_iscsid)
5ebdd5
+{
5ebdd5
+       return ipc_connect(fd, ISCSIADM_NAMESPACE, start_iscsid);
5ebdd5
+}
5ebdd5
+
5ebdd5
 mgmt_ipc_err_e iscsid_request(int *fd, iscsiadm_req_t *req, int start_iscsid)
5ebdd5
 {
5ebdd5
 	int err;
5ebdd5
@@ -190,6 +198,72 @@ int iscsid_req_by_sid(iscsiadm_cmd_e cmd, int sid)
5ebdd5
 	return iscsid_req_wait(cmd, fd);
5ebdd5
 }
5ebdd5
 
5ebdd5
+static mgmt_ipc_err_e uip_connect(int *fd)
5ebdd5
+{
5ebdd5
+	return ipc_connect(fd, ISCSID_UIP_NAMESPACE, 0);
5ebdd5
+}
5ebdd5
+
5ebdd5
+int uip_broadcast(void *buf, size_t buf_len)
5ebdd5
+{
5ebdd5
+	int err;
5ebdd5
+	int fd;
5ebdd5
+	iscsid_uip_rsp_t rsp;
5ebdd5
+	int flags;
5ebdd5
+	int count;
5ebdd5
+
5ebdd5
+	err = uip_connect(&fd);
5ebdd5
+	if (err) {
5ebdd5
+		log_warning("uIP daemon is not up");
5ebdd5
+		return err;
5ebdd5
+	}
5ebdd5
+
5ebdd5
+	/*  Send the data to uIP */
5ebdd5
+	if ((err = write(fd, buf, buf_len)) != buf_len) {
5ebdd5
+		log_error("got write error (%d/%d), daemon died?",
5ebdd5
+			err, errno);
5ebdd5
+		close(fd);
5ebdd5
+		return -EIO;
5ebdd5
+	}
5ebdd5
+
5ebdd5
+	/*  Set the socket to a non-blocking read, this way if there are
5ebdd5
+	 *  problems waiting for uIP, iscsid can bailout early */
5ebdd5
+	flags = fcntl(fd, F_GETFL, 0);
5ebdd5
+	if (flags == -1)
5ebdd5
+	        flags = 0;
5ebdd5
+	err = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
5ebdd5
+	if(err != 0) {
5ebdd5
+		log_error("could not set uip broadcast to non-blocking: %d",
5ebdd5
+			  errno);
5ebdd5
+		close(fd);
5ebdd5
+		return -EIO;
5ebdd5
+	}
5ebdd5
+
5ebdd5
+#define MAX_UIP_BROADCAST_READ_TRIES 3
5ebdd5
+	for(count = 0; count < MAX_UIP_BROADCAST_READ_TRIES; count++) {
5ebdd5
+		/*  Wait for the response */
5ebdd5
+		err = read(fd, &rsp, sizeof(rsp));
5ebdd5
+		if (err == sizeof(rsp)) {
5ebdd5
+			log_debug(3, "Broadcasted to uIP with length: %ld\n",
5ebdd5
+				  buf_len);
5ebdd5
+			break;
5ebdd5
+		} else if((err == -1) && (errno == EAGAIN)) {
5ebdd5
+			usleep(250000);
5ebdd5
+			continue;
5ebdd5
+		} else {
5ebdd5
+			log_error("Could not read response (%d/%d), daemon died?",
5ebdd5
+				  err, errno);
5ebdd5
+			break;
5ebdd5
+		}
5ebdd5
+	}
5ebdd5
+
5ebdd5
+	if(count == MAX_UIP_BROADCAST_READ_TRIES)
5ebdd5
+		log_error("Could not broadcast to uIP");
5ebdd5
+
5ebdd5
+	close(fd);
5ebdd5
+
5ebdd5
+	return 0;
5ebdd5
+}
5ebdd5
+
5ebdd5
 void iscsid_handle_error(mgmt_ipc_err_e err)
5ebdd5
 {
5ebdd5
 	static char *err_msgs[] = {
5ebdd5
diff --git a/usr/iscsid_req.h b/usr/iscsid_req.h
5ebdd5
index 3bba2f4..e2cf1c3 100644
5ebdd5
--- a/usr/iscsid_req.h
5ebdd5
+++ b/usr/iscsid_req.h
5ebdd5
@@ -34,4 +34,6 @@ extern int iscsid_req_by_rec(int cmd, struct node_rec *rec);
5ebdd5
 extern int iscsid_req_by_sid_async(int cmd, int sid, int *fd);
5ebdd5
 extern int iscsid_req_by_sid(int cmd, int sid);
5ebdd5
 
5ebdd5
+extern int uip_broadcast(void *buf, size_t buf_len);
5ebdd5
+
5ebdd5
 #endif
5ebdd5
diff --git a/usr/transport.c b/usr/transport.c
5ebdd5
index c0789bb..aa0395c 100644
5ebdd5
--- a/usr/transport.c
5ebdd5
+++ b/usr/transport.c
5ebdd5
@@ -25,6 +25,7 @@
5ebdd5
 #include "log.h"
5ebdd5
 #include "iscsi_util.h"
5ebdd5
 #include "iscsi_sysfs.h"
5ebdd5
+#include "uip_mgmt_ipc.h"
5ebdd5
 #include "cxgb3i.h"
5ebdd5
 #include "be2iscsi.h"
5ebdd5
 
5ebdd5
@@ -58,6 +59,7 @@ struct iscsi_transport_template bnx2i = {
5ebdd5
 	.ep_connect	= ktransport_ep_connect,
5ebdd5
 	.ep_poll	= ktransport_ep_poll,
5ebdd5
 	.ep_disconnect	= ktransport_ep_disconnect,
5ebdd5
+	.set_net_config = uip_broadcast_params,
5ebdd5
 };
5ebdd5
 
5ebdd5
 struct iscsi_transport_template be2iscsi = {
5ebdd5
diff --git a/usr/transport.h b/usr/transport.h
5ebdd5
index 5ceedb3..2ec903c 100644
5ebdd5
--- a/usr/transport.h
5ebdd5
+++ b/usr/transport.h
5ebdd5
@@ -35,6 +35,9 @@ struct iscsi_transport_template {
5ebdd5
 	int (*ep_poll) (struct iscsi_conn *conn, int timeout_ms);
5ebdd5
 	void (*ep_disconnect) (struct iscsi_conn *conn);
5ebdd5
 	void (*create_conn) (struct iscsi_conn *conn);
5ebdd5
+	int (*set_net_config) (struct iscsi_transport *t,
5ebdd5
+			       struct iface_rec *iface,
5ebdd5
+			       struct iscsi_session *session);
5ebdd5
 };
5ebdd5
 
5ebdd5
 /* represents data path provider */
5ebdd5
diff --git a/usr/uip_mgmt_ipc.c b/usr/uip_mgmt_ipc.c
5ebdd5
new file mode 100644
5ebdd5
index 0000000..73b1632
5ebdd5
--- /dev/null
5ebdd5
+++ b/usr/uip_mgmt_ipc.c
5ebdd5
@@ -0,0 +1,41 @@
5ebdd5
+/*
5ebdd5
+ * uIP iSCSI Daemon/Admin Management IPC
5ebdd5
+ *
5ebdd5
+ * This program is free software; you can redistribute it and/or modify
5ebdd5
+ * it under the terms of the GNU General Public License as published
5ebdd5
+ * by the Free Software Foundation; either version 2 of the License, or
5ebdd5
+ * (at your option) any later version.
5ebdd5
+ *
5ebdd5
+ * This program is distributed in the hope that it will be useful, but
5ebdd5
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
5ebdd5
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5ebdd5
+ * General Public License for more details.
5ebdd5
+ *
5ebdd5
+ * See the file COPYING included with this distribution for more details.
5ebdd5
+ */
5ebdd5
+
5ebdd5
+#include <string.h>
5ebdd5
+
5ebdd5
+#include "log.h"
5ebdd5
+#include "uip_mgmt_ipc.h"
5ebdd5
+#include "iscsid_req.h"
5ebdd5
+
5ebdd5
+int uip_broadcast_params(struct iscsi_transport *t,
5ebdd5
+			 struct iface_rec *iface,
5ebdd5
+			 struct iscsi_session *session)
5ebdd5
+{
5ebdd5
+	struct iscsid_uip_broadcast broadcast;
5ebdd5
+
5ebdd5
+        log_debug(3, "broadcasting to uip\n");
5ebdd5
+
5ebdd5
+	memset(&broadcast, 0, sizeof(broadcast));
5ebdd5
+
5ebdd5
+	broadcast.header.command = ISCSID_UIP_IPC_GET_IFACE;
5ebdd5
+	broadcast.header.payload_len = sizeof(*iface);
5ebdd5
+
5ebdd5
+	memcpy(&broadcast.u.iface_rec, iface, sizeof(*iface));
5ebdd5
+
5ebdd5
+	return uip_broadcast(&broadcast,
5ebdd5
+			     sizeof(iscsid_uip_broadcast_header_t) +
5ebdd5
+			     sizeof(*iface));
5ebdd5
+}
5ebdd5
diff --git a/usr/uip_mgmt_ipc.h b/usr/uip_mgmt_ipc.h
5ebdd5
new file mode 100644
5ebdd5
index 0000000..dd49c0b
5ebdd5
--- /dev/null
5ebdd5
+++ b/usr/uip_mgmt_ipc.h
5ebdd5
@@ -0,0 +1,71 @@
5ebdd5
+/*
5ebdd5
+ * uIP iSCSI Daemon/Admin Management IPC
5ebdd5
+ *
5ebdd5
+ * This program is free software; you can redistribute it and/or modify
5ebdd5
+ * it under the terms of the GNU General Public License as published
5ebdd5
+ * by the Free Software Foundation; either version 2 of the License, or
5ebdd5
+ * (at your option) any later version.
5ebdd5
+ *
5ebdd5
+ * This program is distributed in the hope that it will be useful, but
5ebdd5
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
5ebdd5
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5ebdd5
+ * General Public License for more details.
5ebdd5
+ *
5ebdd5
+ * See the file COPYING included with this distribution for more details.
5ebdd5
+ */
5ebdd5
+#ifndef UIP_MGMT_IPC_H
5ebdd5
+#define UIP_MGMT_IPC_H
5ebdd5
+
5ebdd5
+#include "types.h"
5ebdd5
+#include "iscsi_if.h"
5ebdd5
+#include "config.h"
5ebdd5
+#include "mgmt_ipc.h"
5ebdd5
+
5ebdd5
+#include "initiator.h"
5ebdd5
+#include "transport.h"
5ebdd5
+
5ebdd5
+#define ISCSID_UIP_NAMESPACE	"ISCSID_UIP_ABSTRACT_NAMESPACE"
5ebdd5
+
5ebdd5
+typedef enum iscsid_uip_cmd {
5ebdd5
+	ISCSID_UIP_IPC_UNKNOWN			= 0,
5ebdd5
+	ISCSID_UIP_IPC_GET_IFACE		= 1,
5ebdd5
+
5ebdd5
+        __ISCSID_UIP_IPC_MAX_COMMAND
5ebdd5
+} iscsid_uip_cmd_e;
5ebdd5
+
5ebdd5
+typedef struct iscsid_uip_broadcast_header {
5ebdd5
+	iscsid_uip_cmd_e command;
5ebdd5
+	uint32_t payload_len;
5ebdd5
+} iscsid_uip_broadcast_header_t;
5ebdd5
+
5ebdd5
+/* IPC Request */
5ebdd5
+typedef struct iscsid_uip_broadcast {
5ebdd5
+	struct iscsid_uip_broadcast_header header;
5ebdd5
+
5ebdd5
+	union {
5ebdd5
+		/* messages */
5ebdd5
+		struct ipc_broadcast_iface_rec {
5ebdd5
+			struct iface_rec rec;
5ebdd5
+		} iface_rec;
5ebdd5
+	} u;
5ebdd5
+} iscsid_uip_broadcast_t;
5ebdd5
+
5ebdd5
+typedef enum iscsid_uip_mgmt_ipc_err {
5ebdd5
+	ISCSID_UIP_MGMT_IPC_OK                     = 0,
5ebdd5
+        ISCISD_UIP_MGMT_IPC_ERR                    = 1,
5ebdd5
+        ISCISD_UIP_MGMT_IPC_ERR_NOT_FOUND          = 2,
5ebdd5
+        ISCISD_UIP_MGMT_IPC_ERR_NOMEM              = 3,
5ebdd5
+} iscsid_uip_mgmt_ipc_err_e;
5ebdd5
+
5ebdd5
+/* IPC Response */
5ebdd5
+typedef struct iscsid_uip_mgmt_rsp {
5ebdd5
+	iscsid_uip_cmd_e command;
5ebdd5
+	iscsid_uip_mgmt_ipc_err_e err;
5ebdd5
+} iscsid_uip_rsp_t;
5ebdd5
+
5ebdd5
+extern int uip_broadcast_params(struct iscsi_transport *t,
5ebdd5
+				struct iface_rec *iface,
5ebdd5
+				struct iscsi_session *session);
5ebdd5
+
5ebdd5
+
5ebdd5
+#endif /* UIP_MGMT_IPC_H */
5ebdd5
-- 
5ebdd5
1.6.6.1
5ebdd5