6bbb925
From 59b5b828b2a763f47fb205aedf202990d64e748c Mon Sep 17 00:00:00 2001
0e55d5b
From: Chris Leech <cleech@redhat.com>
0e55d5b
Date: Mon, 24 Dec 2012 13:37:53 -0800
0e55d5b
Subject: iscsid iscsiuio ipc interface
0e55d5b
0e55d5b
---
0e55d5b
 include/iscsi_err.h    |   2 +
0e55d5b
 usr/Makefile           |   3 +-
0e55d5b
 usr/initiator.c        | 113 ++++++++++++++++++++++++++++++++++++++++++++++++-
0e55d5b
 usr/initiator.h        |   4 ++
0e55d5b
 usr/initiator_common.c |  34 +++++++++++++++
0e55d5b
 usr/iscsi_err.c        |   1 +
0e55d5b
 usr/iscsid_req.c       |  91 +++++++++++++++++++++++++++++++++++++--
0e55d5b
 usr/iscsid_req.h       |   2 +
0e55d5b
 usr/transport.c        |   2 +
0e55d5b
 usr/transport.h        |   3 ++
0e55d5b
 usr/uip_mgmt_ipc.c     |  41 ++++++++++++++++++
0e55d5b
 usr/uip_mgmt_ipc.h     |  73 ++++++++++++++++++++++++++++++++
0e55d5b
 12 files changed, 364 insertions(+), 5 deletions(-)
0e55d5b
 create mode 100644 usr/uip_mgmt_ipc.c
0e55d5b
 create mode 100644 usr/uip_mgmt_ipc.h
0e55d5b
0e55d5b
diff --git a/include/iscsi_err.h b/include/iscsi_err.h
0e55d5b
index aabea4e..1139133 100644
0e55d5b
--- a/include/iscsi_err.h
0e55d5b
+++ b/include/iscsi_err.h
0e55d5b
@@ -62,6 +62,8 @@ enum {
0e55d5b
 	ISCSI_ERR_OP_NOT_SUPP		= 27,
0e55d5b
 	/* device or resource in use */
0e55d5b
 	ISCSI_ERR_BUSY			= 28,
Mike Christie 3949e15
+	/* Operation failed, but retrying layer may succeed */
0e55d5b
+	ISCSI_ERR_AGAIN			= 29,
Mike Christie 3949e15
 
Mike Christie 3949e15
 	/* Always last. Indicates end of error code space */
Mike Christie 3949e15
 	ISCSI_MAX_ERR_VAL,
0e55d5b
diff --git a/usr/Makefile b/usr/Makefile
0e55d5b
index 1669890..5bf5f83 100644
0e55d5b
--- a/usr/Makefile
0e55d5b
+++ b/usr/Makefile
0e55d5b
@@ -40,7 +40,8 @@ SYSDEPS_SRCS = $(wildcard ../utils/sysdeps/*.o)
0e55d5b
 ISCSI_LIB_SRCS = iscsi_util.o io.o auth.o iscsi_timer.o login.o log.o md5.o \
0e55d5b
 	sha1.o iface.o idbm.o sysfs.o host.o session_info.o iscsi_sysfs.o \
0e55d5b
 	iscsi_net_util.o iscsid_req.o transport.o iser.o cxgbi.o be2iscsi.o \
6bbb925
-	initiator_common.o iscsi_err.o iscsi_param.o $(IPC_OBJ)  $(SYSDEPS_SRCS)
6bbb925
+	initiator_common.o iscsi_err.o iscsi_param.o uip_mgmt_ipc.o \
0e55d5b
+	$(IPC_OBJ)  $(SYSDEPS_SRCS)
0e55d5b
 # core initiator files
0e55d5b
 INITIATOR_SRCS = initiator.o scsi.o actor.o event_poll.o mgmt_ipc.o kern_err_table.o
5ebdd59
 
0e55d5b
diff --git a/usr/initiator.c b/usr/initiator.c
0e55d5b
index d475358..597e0ff 100644
0e55d5b
--- a/usr/initiator.c
0e55d5b
+++ b/usr/initiator.c
5ebdd59
@@ -45,6 +45,7 @@
5ebdd59
 #include "iscsi_sysfs.h"
5ebdd59
 #include "iscsi_settings.h"
5ebdd59
 #include "iface.h"
5ebdd59
+#include "host.h"
5ebdd59
 #include "sysdeps.h"
Mike Christie 3949e15
 #include "iscsi_err.h"
0e55d5b
 #include "kern_err_table.h"
0e55d5b
@@ -557,6 +558,48 @@ static int iscsi_conn_connect(struct iscsi_conn *conn, queue_task_t *qtask)
5ebdd59
 	return 0;
5ebdd59
 }
5ebdd59
 
Mike Christie 3949e15
+static void iscsi_uio_poll_login_timedout(void *data)
Mike Christie 3949e15
+{
Mike Christie 3949e15
+	struct queue_task *qtask = data;
Mike Christie 3949e15
+	struct iscsi_conn *conn = qtask->conn;
Mike Christie 3949e15
+	iscsi_session_t *session = conn->session;
Mike Christie 3949e15
+
Mike Christie 3949e15
+	log_debug(3, "timeout waiting for UIO ...\n");
Mike Christie 3949e15
+	mgmt_ipc_write_rsp(qtask, ISCSI_ERR_TRANS_TIMEOUT);
Mike Christie 3949e15
+	conn_delete_timers(conn);
Mike Christie 3949e15
+	__session_destroy(session);
Mike Christie 3949e15
+}
Mike Christie 3949e15
+
Mike Christie 3949e15
+static int iscsi_sched_uio_poll(queue_task_t *qtask)
Mike Christie 3949e15
+{
Mike Christie 3949e15
+	struct iscsi_conn *conn = qtask->conn;
Mike Christie 3949e15
+	struct iscsi_session *session = conn->session;
Mike Christie 3949e15
+	struct iscsi_transport *t = session->t;
Mike Christie 3949e15
+	struct iscsi_ev_context *ev_context;
Mike Christie 3949e15
+
Mike Christie 3949e15
+	if (!t->template->set_net_config)
Mike Christie 3949e15
+		return 0;
Mike Christie 3949e15
+
Mike Christie 3949e15
+	ev_context = iscsi_ev_context_get(conn, 0);
Mike Christie 3949e15
+	if (!ev_context) {
Mike Christie 3949e15
+		/* while reopening the recv pool should be full */
Mike Christie 3949e15
+		log_error("BUG: __session_conn_reopen could "
Mike Christie 3949e15
+			  "not get conn context for recv.");
Mike Christie 3949e15
+		return ENOMEM;
Mike Christie 3949e15
+	}
Mike Christie 3949e15
+
Mike Christie 3949e15
+	ev_context->data = qtask;
Mike Christie 3949e15
+	conn->state = ISCSI_CONN_STATE_XPT_WAIT;
Mike Christie 3949e15
+
Mike Christie 3949e15
+	iscsi_sched_ev_context(ev_context, conn, 0, EV_UIO_POLL);
Mike Christie 3949e15
+
Mike Christie 3949e15
+	log_debug(3, "Setting login UIO poll timer %p timeout %d",
Mike Christie 3949e15
+		  &conn->login_timer, conn->login_timeout);
Mike Christie 3949e15
+	actor_timer(&conn->login_timer, conn->login_timeout * 1000,
Mike Christie 3949e15
+		    iscsi_uio_poll_login_timedout, qtask);
Mike Christie 3949e15
+	return EAGAIN;
Mike Christie 3949e15
+}
Mike Christie 3949e15
+
Mike Christie 3949e15
 static void
Mike Christie 3949e15
 __session_conn_reopen(iscsi_conn_t *conn, queue_task_t *qtask, int do_stop,
Mike Christie 3949e15
 		      int redirected)
0e55d5b
@@ -598,6 +641,11 @@ __session_conn_reopen(iscsi_conn_t *conn, queue_task_t *qtask, int do_stop,
Mike Christie 3949e15
 	if (!redirected)
Mike Christie 3949e15
 		session->reopen_cnt++;
Mike Christie 3949e15
 
Mike Christie 3949e15
+	/* uIP will needs to be re-triggered on the connection re-open */
Mike Christie 3949e15
+	if (iscsi_set_net_config(conn->session->t, conn->session,
Mike Christie 3949e15
+				 &conn->session->nrec.iface) != 0)
Mike Christie 3949e15
+		goto queue_reopen;
Mike Christie 3949e15
+
Mike Christie 3949e15
 	if (iscsi_conn_connect(conn, qtask)) {
Mike Christie 3949e15
 		delay = ISCSI_CONN_ERR_REOPEN_DELAY;
Mike Christie 3949e15
 		goto queue_reopen;
0e55d5b
@@ -1670,6 +1718,53 @@ failed_login:
Mike Christie 3949e15
 
Mike Christie 3949e15
 }
Mike Christie 3949e15
 
Mike Christie 3949e15
+static void session_conn_uio_poll(void *data)
Mike Christie 3949e15
+{
Mike Christie 3949e15
+	struct iscsi_ev_context *ev_context = data;
Mike Christie 3949e15
+	iscsi_conn_t *conn = ev_context->conn;
Mike Christie 3949e15
+	struct iscsi_session *session = conn->session;
Mike Christie 3949e15
+	queue_task_t *qtask = ev_context->data;
Mike Christie 3949e15
+	int rc;
Mike Christie 3949e15
+
Mike Christie 3949e15
+	log_debug(4, "retrying uio poll");
Mike Christie 3949e15
+	rc = iscsi_set_net_config(session->t, session,
Mike Christie 3949e15
+				  &conn->session->nrec.iface);
Mike Christie 3949e15
+	if (rc != 0) {
Mike Christie 3949e15
+		if (rc == ISCSI_ERR_AGAIN) {
Mike Christie 3949e15
+			ev_context->data = qtask;
Mike Christie 3949e15
+			iscsi_sched_ev_context(ev_context, conn, 2,
Mike Christie 3949e15
+					       EV_UIO_POLL);
Mike Christie 3949e15
+			return;
Mike Christie 3949e15
+		} else {
Mike Christie 3949e15
+			log_error("session_conn_uio_poll() "
Mike Christie 3949e15
+				  "connection failure [0x%x]", rc);
Mike Christie 3949e15
+			actor_delete(&conn->login_timer);
Mike Christie 3949e15
+			iscsi_login_eh(conn, qtask, ISCSI_ERR_INTERNAL);
Mike Christie 3949e15
+			iscsi_ev_context_put(ev_context);
Mike Christie 3949e15
+			return;
Mike Christie 3949e15
+		}
Mike Christie 3949e15
+	}
Mike Christie 3949e15
+
Mike Christie 3949e15
+	iscsi_ev_context_put(ev_context);
Mike Christie 3949e15
+	actor_delete(&conn->login_timer);
Mike Christie 3949e15
+	log_debug(4, "UIO ready trying connect");
Mike Christie 3949e15
+
Mike Christie 3949e15
+	/*  uIP is ready try to connect */
Mike Christie 3949e15
+	if (gettimeofday(&conn->initial_connect_time, NULL))
Mike Christie 3949e15
+		log_error("Could not get initial connect time. If "
Mike Christie 3949e15
+			  "login errors iscsid may give up the initial "
Mike Christie 3949e15
+			  "login early. You should manually login.");
Mike Christie 3949e15
+
Mike Christie 3949e15
+	conn->state = ISCSI_CONN_STATE_XPT_WAIT;
Mike Christie 3949e15
+	if (iscsi_conn_connect(conn, qtask)) {
Mike Christie 3949e15
+		int delay = ISCSI_CONN_ERR_REOPEN_DELAY;
Mike Christie 3949e15
+
Mike Christie 3949e15
+		log_debug(4, "Waiting %u seconds before trying to reconnect.\n",
Mike Christie 3949e15
+			  delay);
Mike Christie 3949e15
+		queue_delayed_reopen(qtask, delay);
Mike Christie 3949e15
+	}
Mike Christie 3949e15
+}
Mike Christie 3949e15
+
Mike Christie 3949e15
 static int iscsi_sched_ev_context(struct iscsi_ev_context *ev_context,
Mike Christie 3949e15
 				  struct iscsi_conn *conn, unsigned long tmo,
Mike Christie 3949e15
 				  int event)
0e55d5b
@@ -1711,6 +1806,11 @@ static int iscsi_sched_ev_context(struct iscsi_ev_context *ev_context,
Mike Christie 3949e15
 			  ev_context);
Mike Christie 3949e15
 		actor_schedule(&ev_context->actor);
Mike Christie 3949e15
 		break;
Mike Christie 3949e15
+	case EV_UIO_POLL:
Mike Christie 3949e15
+		actor_new(&ev_context->actor, session_conn_uio_poll,
Mike Christie 3949e15
+			  ev_context);
Mike Christie 3949e15
+		actor_schedule(&ev_context->actor);
Mike Christie 3949e15
+		break;
Mike Christie 3949e15
 	case EV_CONN_LOGOUT_TIMER:
Mike Christie 3949e15
 		actor_timer(&ev_context->actor, tmo * 1000,
Mike Christie 3949e15
 			    iscsi_logout_timedout, ev_context);
0e55d5b
@@ -1844,7 +1944,17 @@ session_login_task(node_rec_t *rec, queue_task_t *qtask)
Mike Christie 3949e15
 	conn = &session->conn[0];
Mike Christie 3949e15
 	qtask->conn = conn;
Mike Christie 3949e15
 
Mike Christie 3949e15
-	if (iscsi_host_set_net_params(&rec->iface, session)) {
Mike Christie 3949e15
+	rc = iscsi_host_set_net_params(&rec->iface, session);
Mike Christie 3949e15
+	if (rc == ISCSI_ERR_AGAIN) {
Mike Christie 3949e15
+		iscsi_sched_uio_poll(qtask);
Mike Christie 3949e15
+		/*
Mike Christie 3949e15
+		 * Cannot block iscsid, so caller is going to internally
Mike Christie 3949e15
+		 * retry the operation.
Mike Christie 3949e15
+		 */
Mike Christie 3949e15
+		qtask->rsp.command = MGMT_IPC_SESSION_LOGIN;
Mike Christie 3949e15
+		qtask->rsp.err = ISCSI_SUCCESS;
Mike Christie 3949e15
+		return ISCSI_SUCCESS;
Mike Christie 3949e15
+	} else if (rc) {
Mike Christie 3949e15
 		__session_destroy(session);
Mike Christie 3949e15
 		return ISCSI_ERR_LOGIN;
Mike Christie 3949e15
 	}
0e55d5b
@@ -2001,6 +2111,7 @@ iscsi_host_send_targets(queue_task_t *qtask, int host_no, int do_login,
Mike Christie 3949e15
 			struct sockaddr_storage *ss)
Mike Christie 3949e15
 {
Mike Christie 3949e15
 	struct iscsi_transport *t;
Mike Christie 3949e15
+	int rc;
Mike Christie 3949e15
 
Mike Christie 3949e15
 	t = iscsi_sysfs_get_transport_by_hba(host_no);
Mike Christie 3949e15
 	if (!t) {
0e55d5b
diff --git a/usr/initiator.h b/usr/initiator.h
0e55d5b
index b45caab..d6dc02e 100644
0e55d5b
--- a/usr/initiator.h
0e55d5b
+++ b/usr/initiator.h
0e55d5b
@@ -83,6 +83,7 @@ typedef enum iscsi_event_e {
0e55d5b
 	EV_CONN_LOGOUT_TIMER,
0e55d5b
 	EV_CONN_STOP,
0e55d5b
 	EV_CONN_LOGIN,
0e55d5b
+	EV_UIO_POLL,
0e55d5b
 } iscsi_event_e;
0e55d5b
 
0e55d5b
 struct queue_task;
0e55d5b
@@ -353,5 +354,8 @@ extern void iscsi_copy_operational_params(struct iscsi_conn *conn,
0e55d5b
 extern int iscsi_setup_authentication(struct iscsi_session *session,
0e55d5b
 				      struct iscsi_auth_config *auth_cfg);
0e55d5b
 extern int iscsi_setup_portal(struct iscsi_conn *conn, char *address, int port);
0e55d5b
+extern int iscsi_set_net_config(struct iscsi_transport *t,
0e55d5b
+				iscsi_session_t *session,
0e55d5b
+				struct iface_rec *iface);
0e55d5b
 
0e55d5b
 #endif /* INITIATOR_H */
0e55d5b
diff --git a/usr/initiator_common.c b/usr/initiator_common.c
0e55d5b
index ef6820c..eb72795 100644
0e55d5b
--- a/usr/initiator_common.c
0e55d5b
+++ b/usr/initiator_common.c
0e55d5b
@@ -562,6 +562,36 @@ TODO handle this
Mike Christie 3949e15
 	return 0;
Mike Christie 3949e15
 }
Mike Christie 3949e15
 
Mike Christie 3949e15
+int iscsi_set_net_config(struct iscsi_transport *t, iscsi_session_t *session,
Mike Christie 3949e15
+			 struct iface_rec *iface)
5ebdd59
+{
5ebdd59
+	if (t->template->set_net_config) {
5ebdd59
+		/* uip needs the netdev name */
5ebdd59
+		struct host_info hinfo;
5ebdd59
+		int hostno, rc;
5ebdd59
+
5ebdd59
+		/* this assumes that the netdev or hw address is going to be
5ebdd59
+		   set */
5ebdd59
+		hostno = iscsi_sysfs_get_host_no_from_hwinfo(iface, &rc);
5ebdd59
+		if (rc) {
5ebdd59
+			log_debug(4, "Couldn't get host no.\n");
5ebdd59
+			return rc;
5ebdd59
+		}
5ebdd59
+
5ebdd59
+		/* uip needs the netdev name */
5ebdd59
+		if (!strlen(iface->netdev)) {
5ebdd59
+			memset(&hinfo, 0, sizeof(hinfo));
5ebdd59
+			hinfo.host_no = hostno;
5ebdd59
+			iscsi_sysfs_get_hostinfo_by_host_no(&hinfo);
5ebdd59
+			strcpy(iface->netdev, hinfo.iface.netdev);
5ebdd59
+		}
5ebdd59
+
5ebdd59
+		return t->template->set_net_config(t, iface, session);
5ebdd59
+	}
5ebdd59
+
5ebdd59
+	return 0;
5ebdd59
+}
5ebdd59
+
Mike Christie 3949e15
 int iscsi_host_set_net_params(struct iface_rec *iface,
Mike Christie 3949e15
 			      struct iscsi_session *session)
Mike Christie 3949e15
 {
0e55d5b
@@ -600,6 +630,10 @@ int iscsi_host_set_net_params(struct iface_rec *iface,
0e55d5b
 		log_warning("Could not brining up netdev %s. Try running "
0e55d5b
 			    "'ifup %s' first if login fails.", netdev, netdev);
5ebdd59
 
Mike Christie 3949e15
+	rc = iscsi_set_net_config(t, session, iface);
5ebdd59
+	if (rc != 0)
5ebdd59
+		return rc;
5ebdd59
+
Mike Christie 3949e15
 	rc = host_set_param(t, session->hostno,
Mike Christie 3949e15
 			    ISCSI_HOST_PARAM_IPADDRESS,
Mike Christie 3949e15
 			    iface->ipaddress, ISCSI_STRING);
0e55d5b
diff --git a/usr/iscsi_err.c b/usr/iscsi_err.c
0e55d5b
index 4fe1c53..f9ba130 100644
0e55d5b
--- a/usr/iscsi_err.c
0e55d5b
+++ b/usr/iscsi_err.c
0e55d5b
@@ -51,6 +51,7 @@ static char *iscsi_err_msgs[] = {
0e55d5b
 	/* 26 */ "iSNS registration failed",
0e55d5b
 	/* 27 */ "operation not supported",
0e55d5b
 	/* 28 */ "device or resource in use",
0e55d5b
+	/* 29 */ "Retryable failure",
0e55d5b
 };
Mike Christie 3949e15
 
0e55d5b
 char *iscsi_err_to_str(int err)
0e55d5b
diff --git a/usr/iscsid_req.c b/usr/iscsid_req.c
0e55d5b
index 1c4678d..a436194 100644
0e55d5b
--- a/usr/iscsid_req.c
0e55d5b
+++ b/usr/iscsid_req.c
5ebdd59
@@ -22,6 +22,7 @@
5ebdd59
 #include <stdlib.h>
5ebdd59
 #include <string.h>
5ebdd59
 #include <errno.h>
5ebdd59
+#include <fcntl.h>
5ebdd59
 #include <sys/un.h>
5ebdd59
 #include <sys/types.h>
5ebdd59
 #include <sys/socket.h>
Mike Christie 3949e15
@@ -32,6 +33,7 @@
5ebdd59
 #include "iscsi_util.h"
5ebdd59
 #include "config.h"
Mike Christie 3949e15
 #include "iscsi_err.h"
5ebdd59
+#include "uip_mgmt_ipc.h"
5ebdd59
 
5ebdd59
 static void iscsid_startup(void)
5ebdd59
 {
Mike Christie 3949e15
@@ -54,7 +56,7 @@ static void iscsid_startup(void)
5ebdd59
 
5ebdd59
 #define MAXSLEEP 128
5ebdd59
 
Mike Christie 3949e15
-static int iscsid_connect(int *fd, int start_iscsid)
Mike Christie 3949e15
+static int ipc_connect(int *fd, char *unix_sock_name, int start_iscsid)
5ebdd59
 {
0e55d5b
 	int nsec, addr_len;
5ebdd59
 	struct sockaddr_un addr;
0e55d5b
@@ -65,11 +67,11 @@ static int iscsid_connect(int *fd, int start_iscsid)
0e55d5b
 		return ISCSI_ERR_ISCSID_NOTCONN;
0e55d5b
 	}
0e55d5b
 
0e55d5b
-	addr_len = offsetof(struct sockaddr_un, sun_path) + strlen(ISCSIADM_NAMESPACE) + 1;
0e55d5b
+	addr_len = offsetof(struct sockaddr_un, sun_path) + strlen(unix_sock_name) + 1;
5ebdd59
 
5ebdd59
 	memset(&addr, 0, sizeof(addr));
5ebdd59
 	addr.sun_family = AF_LOCAL;
0e55d5b
-	memcpy((char *) &addr.sun_path + 1, ISCSIADM_NAMESPACE, addr_len);
0e55d5b
+	memcpy((char *) &addr.sun_path + 1, unix_sock_name, addr_len);
0e55d5b
 
5ebdd59
 	/*
5ebdd59
 	 * Trying to connect with exponential backoff
0e55d5b
@@ -98,6 +100,11 @@ static int iscsid_connect(int *fd, int start_iscsid)
Mike Christie 3949e15
 	return ISCSI_ERR_ISCSID_NOTCONN;
5ebdd59
 }
5ebdd59
 
Mike Christie 3949e15
+static int iscsid_connect(int *fd, int start_iscsid)
5ebdd59
+{
Mike Christie 3949e15
+	return ipc_connect(fd, ISCSIADM_NAMESPACE, start_iscsid);
5ebdd59
+}
5ebdd59
+
Mike Christie 3949e15
 int iscsid_request(int *fd, iscsiadm_req_t *req, int start_iscsid)
5ebdd59
 {
5ebdd59
 	int err;
0e55d5b
@@ -194,3 +201,81 @@ int iscsid_req_by_sid(iscsiadm_cmd_e cmd, int sid)
Mike Christie 3949e15
 		return err;
5ebdd59
 	return iscsid_req_wait(cmd, fd);
5ebdd59
 }
Mike Christie 3949e15
+
Mike Christie 3949e15
+static int uip_connect(int *fd)
5ebdd59
+{
5ebdd59
+	return ipc_connect(fd, ISCSID_UIP_NAMESPACE, 0);
5ebdd59
+}
5ebdd59
+
5ebdd59
+int uip_broadcast(void *buf, size_t buf_len)
5ebdd59
+{
5ebdd59
+	int err;
5ebdd59
+	int fd;
5ebdd59
+	iscsid_uip_rsp_t rsp;
5ebdd59
+	int flags;
5ebdd59
+	int count;
5ebdd59
+
5ebdd59
+	err = uip_connect(&fd;;
5ebdd59
+	if (err) {
5ebdd59
+		log_warning("uIP daemon is not up");
5ebdd59
+		return err;
5ebdd59
+	}
5ebdd59
+
Mike Christie 3949e15
+	log_debug(3, "connected to uIP daemon");
Mike Christie 3949e15
+
5ebdd59
+	/*  Send the data to uIP */
5ebdd59
+	if ((err = write(fd, buf, buf_len)) != buf_len) {
5ebdd59
+		log_error("got write error (%d/%d), daemon died?",
Mike Christie 3949e15
+			  err, errno);
5ebdd59
+		close(fd);
Mike Christie 3949e15
+		return ISCSI_ERR_ISCSID_COMM_ERR;
5ebdd59
+	}
5ebdd59
+
Mike Christie 3949e15
+	log_debug(3, "send iface config to uIP daemon");
Mike Christie 3949e15
+
5ebdd59
+	/*  Set the socket to a non-blocking read, this way if there are
5ebdd59
+	 *  problems waiting for uIP, iscsid can bailout early */
5ebdd59
+	flags = fcntl(fd, F_GETFL, 0);
5ebdd59
+	if (flags == -1)
Mike Christie 3949e15
+		flags = 0;
5ebdd59
+	err = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
5ebdd59
+	if(err != 0) {
5ebdd59
+		log_error("could not set uip broadcast to non-blocking: %d",
5ebdd59
+			  errno);
5ebdd59
+		close(fd);
Mike Christie 3949e15
+		return ISCSI_ERR;
5ebdd59
+	}
5ebdd59
+
5ebdd59
+#define MAX_UIP_BROADCAST_READ_TRIES 3
5ebdd59
+	for(count = 0; count < MAX_UIP_BROADCAST_READ_TRIES; count++) {
5ebdd59
+		/*  Wait for the response */
5ebdd59
+		err = read(fd, &rsp, sizeof(rsp));
5ebdd59
+		if (err == sizeof(rsp)) {
Mike Christie 3949e15
+			log_debug(3, "Broadcasted to uIP with length: %ld "
Mike Christie 3949e15
+				     "cmd: 0x%x rsp: 0x%x\n", buf_len,
Mike Christie 3949e15
+				     rsp.command, rsp.err);
Mike Christie 3949e15
+			err = 0;
5ebdd59
+			break;
5ebdd59
+		} else if((err == -1) && (errno == EAGAIN)) {
5ebdd59
+			usleep(250000);
5ebdd59
+			continue;
5ebdd59
+		} else {
5ebdd59
+			log_error("Could not read response (%d/%d), daemon died?",
5ebdd59
+				  err, errno);
Mike Christie 3949e15
+			err = ISCSI_ERR;
5ebdd59
+			break;
5ebdd59
+		}
5ebdd59
+	}
5ebdd59
+
Mike Christie 3949e15
+	if (count == MAX_UIP_BROADCAST_READ_TRIES) {
Mike Christie 3949e15
+		log_error("Could not broadcast to uIP after %d tries",
Mike Christie 3949e15
+			  count);
Mike Christie 3949e15
+		err = ISCSI_ERR_AGAIN;
Mike Christie 3949e15
+	} else if (rsp.err != ISCISD_UIP_MGMT_IPC_DEVICE_UP) {
Mike Christie 3949e15
+		log_debug(3, "Device is not ready\n");
Mike Christie 3949e15
+		err = ISCSI_ERR_AGAIN;
Mike Christie 3949e15
+	}
5ebdd59
+
5ebdd59
+	close(fd);
Mike Christie 3949e15
+	return err;
5ebdd59
+}
0e55d5b
diff --git a/usr/iscsid_req.h b/usr/iscsid_req.h
0e55d5b
index 68f5256..4fff43d 100644
0e55d5b
--- a/usr/iscsid_req.h
0e55d5b
+++ b/usr/iscsid_req.h
0e55d5b
@@ -33,4 +33,6 @@ extern int iscsid_req_by_rec(int cmd, struct node_rec *rec);
5ebdd59
 extern int iscsid_req_by_sid_async(int cmd, int sid, int *fd);
5ebdd59
 extern int iscsid_req_by_sid(int cmd, int sid);
5ebdd59
 
5ebdd59
+extern int uip_broadcast(void *buf, size_t buf_len);
5ebdd59
+
5ebdd59
 #endif
0e55d5b
diff --git a/usr/transport.c b/usr/transport.c
0e55d5b
index e6e3dfc..10212af 100644
0e55d5b
--- a/usr/transport.c
0e55d5b
+++ b/usr/transport.c
0e55d5b
@@ -35,6 +35,7 @@
5ebdd59
 #include "log.h"
5ebdd59
 #include "iscsi_util.h"
5ebdd59
 #include "iscsi_sysfs.h"
5ebdd59
+#include "uip_mgmt_ipc.h"
Mike Christie 3949e15
 #include "cxgbi.h"
5ebdd59
 #include "be2iscsi.h"
0e55d5b
 #include "iser.h"
0e55d5b
@@ -79,6 +80,7 @@ struct iscsi_transport_template bnx2i = {
5ebdd59
 	.ep_connect	= ktransport_ep_connect,
5ebdd59
 	.ep_poll	= ktransport_ep_poll,
5ebdd59
 	.ep_disconnect	= ktransport_ep_disconnect,
5ebdd59
+	.set_net_config = uip_broadcast_params,
5ebdd59
 };
5ebdd59
 
5ebdd59
 struct iscsi_transport_template be2iscsi = {
0e55d5b
diff --git a/usr/transport.h b/usr/transport.h
0e55d5b
index 672561b..5dcf872 100644
0e55d5b
--- a/usr/transport.h
0e55d5b
+++ b/usr/transport.h
5ebdd59
@@ -35,6 +35,9 @@ struct iscsi_transport_template {
5ebdd59
 	int (*ep_poll) (struct iscsi_conn *conn, int timeout_ms);
5ebdd59
 	void (*ep_disconnect) (struct iscsi_conn *conn);
5ebdd59
 	void (*create_conn) (struct iscsi_conn *conn);
5ebdd59
+	int (*set_net_config) (struct iscsi_transport *t,
5ebdd59
+			       struct iface_rec *iface,
5ebdd59
+			       struct iscsi_session *session);
5ebdd59
 };
5ebdd59
 
5ebdd59
 /* represents data path provider */
0e55d5b
diff --git a/usr/uip_mgmt_ipc.c b/usr/uip_mgmt_ipc.c
0e55d5b
new file mode 100644
0e55d5b
index 0000000..73b1632
0e55d5b
--- /dev/null
0e55d5b
+++ b/usr/uip_mgmt_ipc.c
5ebdd59
@@ -0,0 +1,41 @@
5ebdd59
+/*
5ebdd59
+ * uIP iSCSI Daemon/Admin Management IPC
5ebdd59
+ *
5ebdd59
+ * This program is free software; you can redistribute it and/or modify
5ebdd59
+ * it under the terms of the GNU General Public License as published
5ebdd59
+ * by the Free Software Foundation; either version 2 of the License, or
5ebdd59
+ * (at your option) any later version.
5ebdd59
+ *
5ebdd59
+ * This program is distributed in the hope that it will be useful, but
5ebdd59
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
5ebdd59
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5ebdd59
+ * General Public License for more details.
5ebdd59
+ *
5ebdd59
+ * See the file COPYING included with this distribution for more details.
5ebdd59
+ */
5ebdd59
+
5ebdd59
+#include <string.h>
5ebdd59
+
5ebdd59
+#include "log.h"
5ebdd59
+#include "uip_mgmt_ipc.h"
5ebdd59
+#include "iscsid_req.h"
5ebdd59
+
5ebdd59
+int uip_broadcast_params(struct iscsi_transport *t,
5ebdd59
+			 struct iface_rec *iface,
5ebdd59
+			 struct iscsi_session *session)
5ebdd59
+{
5ebdd59
+	struct iscsid_uip_broadcast broadcast;
5ebdd59
+
5ebdd59
+        log_debug(3, "broadcasting to uip\n");
5ebdd59
+
5ebdd59
+	memset(&broadcast, 0, sizeof(broadcast));
5ebdd59
+
5ebdd59
+	broadcast.header.command = ISCSID_UIP_IPC_GET_IFACE;
5ebdd59
+	broadcast.header.payload_len = sizeof(*iface);
5ebdd59
+
5ebdd59
+	memcpy(&broadcast.u.iface_rec, iface, sizeof(*iface));
5ebdd59
+
5ebdd59
+	return uip_broadcast(&broadcast,
5ebdd59
+			     sizeof(iscsid_uip_broadcast_header_t) +
5ebdd59
+			     sizeof(*iface));
5ebdd59
+}
0e55d5b
diff --git a/usr/uip_mgmt_ipc.h b/usr/uip_mgmt_ipc.h
0e55d5b
new file mode 100644
0e55d5b
index 0000000..3859688
0e55d5b
--- /dev/null
0e55d5b
+++ b/usr/uip_mgmt_ipc.h
Mike Christie 3949e15
@@ -0,0 +1,73 @@
5ebdd59
+/*
5ebdd59
+ * uIP iSCSI Daemon/Admin Management IPC
5ebdd59
+ *
5ebdd59
+ * This program is free software; you can redistribute it and/or modify
5ebdd59
+ * it under the terms of the GNU General Public License as published
5ebdd59
+ * by the Free Software Foundation; either version 2 of the License, or
5ebdd59
+ * (at your option) any later version.
5ebdd59
+ *
5ebdd59
+ * This program is distributed in the hope that it will be useful, but
5ebdd59
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
5ebdd59
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5ebdd59
+ * General Public License for more details.
5ebdd59
+ *
5ebdd59
+ * See the file COPYING included with this distribution for more details.
5ebdd59
+ */
5ebdd59
+#ifndef UIP_MGMT_IPC_H
5ebdd59
+#define UIP_MGMT_IPC_H
5ebdd59
+
5ebdd59
+#include "types.h"
5ebdd59
+#include "iscsi_if.h"
5ebdd59
+#include "config.h"
5ebdd59
+#include "mgmt_ipc.h"
5ebdd59
+
5ebdd59
+#include "initiator.h"
5ebdd59
+#include "transport.h"
5ebdd59
+
5ebdd59
+#define ISCSID_UIP_NAMESPACE	"ISCSID_UIP_ABSTRACT_NAMESPACE"
5ebdd59
+
5ebdd59
+typedef enum iscsid_uip_cmd {
5ebdd59
+	ISCSID_UIP_IPC_UNKNOWN			= 0,
5ebdd59
+	ISCSID_UIP_IPC_GET_IFACE		= 1,
5ebdd59
+
5ebdd59
+        __ISCSID_UIP_IPC_MAX_COMMAND
5ebdd59
+} iscsid_uip_cmd_e;
5ebdd59
+
5ebdd59
+typedef struct iscsid_uip_broadcast_header {
5ebdd59
+	iscsid_uip_cmd_e command;
5ebdd59
+	uint32_t payload_len;
5ebdd59
+} iscsid_uip_broadcast_header_t;
5ebdd59
+
5ebdd59
+/* IPC Request */
5ebdd59
+typedef struct iscsid_uip_broadcast {
5ebdd59
+	struct iscsid_uip_broadcast_header header;
5ebdd59
+
5ebdd59
+	union {
5ebdd59
+		/* messages */
5ebdd59
+		struct ipc_broadcast_iface_rec {
5ebdd59
+			struct iface_rec rec;
5ebdd59
+		} iface_rec;
5ebdd59
+	} u;
5ebdd59
+} iscsid_uip_broadcast_t;
5ebdd59
+
5ebdd59
+typedef enum iscsid_uip_mgmt_ipc_err {
5ebdd59
+	ISCSID_UIP_MGMT_IPC_OK                     = 0,
5ebdd59
+        ISCISD_UIP_MGMT_IPC_ERR                    = 1,
5ebdd59
+        ISCISD_UIP_MGMT_IPC_ERR_NOT_FOUND          = 2,
5ebdd59
+        ISCISD_UIP_MGMT_IPC_ERR_NOMEM              = 3,
Mike Christie 3949e15
+	ISCISD_UIP_MGMT_IPC_DEVICE_UP              = 4,
Mike Christie 3949e15
+	ISCISD_UIP_MGMT_IPC_DEVICE_INITIALIZING    = 5,
5ebdd59
+} iscsid_uip_mgmt_ipc_err_e;
5ebdd59
+
5ebdd59
+/* IPC Response */
5ebdd59
+typedef struct iscsid_uip_mgmt_rsp {
5ebdd59
+	iscsid_uip_cmd_e command;
5ebdd59
+	iscsid_uip_mgmt_ipc_err_e err;
5ebdd59
+} iscsid_uip_rsp_t;
5ebdd59
+
5ebdd59
+extern int uip_broadcast_params(struct iscsi_transport *t,
5ebdd59
+				struct iface_rec *iface,
5ebdd59
+				struct iscsi_session *session);
5ebdd59
+
5ebdd59
+
5ebdd59
+#endif /* UIP_MGMT_IPC_H */
0e55d5b
-- 
0e55d5b
1.7.11.7
0e55d5b