From 56c155b5ca427c9a6312bb0e31865f1c8ab10b2b Mon Sep 17 00:00:00 2001
From: Mike Christie <michaelc@cs.wisc.edu>
Date: Mon, 25 Jul 2011 13:48:37 -0500
Subject: [PATCH] [SCSI] iscsi_transport: add support for net settings

Allows user space (iscsiadm) to send down network configuration
parameters for LLD to set private network configuration on the iSCSI
adapters.

Based on patch from Lalit Chandivade.

Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
---
 drivers/scsi/scsi_transport_iscsi.c | 27 +++++++++++++
 include/scsi/iscsi_if.h             | 63 +++++++++++++++++++++++++++++
 include/scsi/scsi_transport_iscsi.h |  1 +
 3 files changed, 91 insertions(+)

diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 3fd16d7212de2e..212a8d84674860 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -1557,6 +1557,30 @@ iscsi_set_path(struct iscsi_transport *transport, struct iscsi_uevent *ev)
 	return err;
 }
 
+static int
+iscsi_set_iface_params(struct iscsi_transport *transport,
+		       struct iscsi_uevent *ev)
+{
+	char *data = (char *)ev + sizeof(*ev);
+	struct Scsi_Host *shost;
+	int err;
+
+	if (!transport->set_iface_param)
+		return -ENOSYS;
+
+	shost = scsi_host_lookup(ev->u.set_iface_params.host_no);
+	if (!shost) {
+		printk(KERN_ERR "set_iface_params could not find host no %u\n",
+		       ev->u.set_iface_params.host_no);
+		return -ENODEV;
+	}
+
+	err = transport->set_iface_param(shost, data,
+					 ev->u.set_iface_params.count);
+	scsi_host_put(shost);
+	return err;
+}
+
 static int
 iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
 {
@@ -1696,6 +1720,9 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
 	case ISCSI_UEVENT_PATH_UPDATE:
 		err = iscsi_set_path(transport, ev);
 		break;
+	case ISCSI_UEVENT_SET_IFACE_PARAMS:
+		err = iscsi_set_iface_params(transport, ev);
+		break;
 	default:
 		err = -ENOSYS;
 		break;
diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
index ddb04568a50976..e93831e8787811 100644
--- a/include/scsi/iscsi_if.h
+++ b/include/scsi/iscsi_if.h
@@ -59,6 +59,7 @@ enum iscsi_uevent_e {
 	ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST	= UEVENT_BASE + 19,
 
 	ISCSI_UEVENT_PATH_UPDATE	= UEVENT_BASE + 20,
+	ISCSI_UEVENT_SET_IFACE_PARAMS	= UEVENT_BASE + 21,
 
 	/* up events */
 	ISCSI_KEVENT_RECV_PDU		= KEVENT_BASE + 1,
@@ -172,6 +173,10 @@ struct iscsi_uevent {
 		struct msg_set_path {
 			uint32_t	host_no;
 		} set_path;
+		struct msg_set_iface_params {
+			uint32_t	host_no;
+			uint32_t	count;
+		} set_iface_params;
 	} u;
 	union {
 		/* messages k -> u */
@@ -214,6 +219,21 @@ struct iscsi_uevent {
 	} r;
 } __attribute__ ((aligned (sizeof(uint64_t))));
 
+enum iscsi_param_type {
+	ISCSI_PARAM,		/* iscsi_param (session, conn, target, LU) */
+	ISCSI_HOST_PARAM,	/* iscsi_host_param */
+	ISCSI_NET_PARAM,	/* iscsi_net_param */
+};
+
+struct iscsi_iface_param_info {
+	uint32_t iface_num;	/* iface number, 0 - n */
+	uint32_t len;		/* Actual length of the param */
+	uint16_t param;		/* iscsi param value */
+	uint8_t iface_type;	/* IPv4 or IPv6 */
+	uint8_t param_type;	/* iscsi_param_type */
+	uint8_t value[0];	/* length sized value follows */
+} __packed;
+
 /*
  * To keep the struct iscsi_uevent size the same for userspace code
  * compatibility, the main structure for ISCSI_UEVENT_PATH_UPDATE and
@@ -237,6 +257,49 @@ struct iscsi_path {
 	uint16_t	pmtu;
 } __attribute__ ((aligned (sizeof(uint64_t))));
 
+/* iscsi iface enabled/disabled setting */
+#define ISCSI_IFACE_DISABLE	0x01
+#define ISCSI_IFACE_ENABLE	0x02
+
+/* ipv4 bootproto */
+#define ISCSI_BOOTPROTO_STATIC		0x01
+#define ISCSI_BOOTPROTO_DHCP		0x02
+
+/* ipv6 addr autoconfig type */
+#define ISCSI_IPV6_AUTOCFG_DISABLE		0x01
+#define ISCSI_IPV6_AUTOCFG_ND_ENABLE		0x02
+#define ISCSI_IPV6_AUTOCFG_DHCPV6_ENABLE	0x03
+
+/* ipv6 link local addr type */
+#define ISCSI_IPV6_LINKLOCAL_AUTOCFG_ENABLE	0x01
+#define ISCSI_IPV6_LINKLOCAL_AUTOCFG_DISABLE	0x02
+
+/* ipv6 router addr type */
+#define ISCSI_IPV6_ROUTER_AUTOCFG_ENABLE	0x01
+#define ISCSI_IPV6_ROUTER_AUTOCFG_DISABLE	0x02
+
+#define ISCSI_IFACE_TYPE_IPV4		0x01
+#define ISCSI_IFACE_TYPE_IPV6		0x02
+
+/* iSCSI network params */
+enum iscsi_net_param {
+	ISCSI_NET_PARAM_IPV4_ADDR		= 1,
+	ISCSI_NET_PARAM_IPV4_SUBNET		= 2,
+	ISCSI_NET_PARAM_IPV4_GW			= 3,
+	ISCSI_NET_PARAM_IPV4_BOOTPROTO		= 4,
+	ISCSI_NET_PARAM_MAC			= 5,
+	ISCSI_NET_PARAM_IPV6_LINKLOCAL		= 6,
+	ISCSI_NET_PARAM_IPV6_ADDR		= 7,
+	ISCSI_NET_PARAM_IPV6_ROUTER		= 8,
+	ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG	= 9,
+	ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG	= 10,
+	ISCSI_NET_PARAM_IPV6_ROUTER_AUTOCFG	= 11,
+	ISCSI_NET_PARAM_IFACE_ENABLE		= 12,
+	ISCSI_NET_PARAM_VLAN_ID			= 13,
+	ISCSI_NET_IFACE_TYPE			= 14,
+	ISCSI_NET_IFACE_NAME			= 15,
+};
+
 /*
  * Common error codes
  */
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
index bf8f5296567557..9fcce7cd36733c 100644
--- a/include/scsi/scsi_transport_iscsi.h
+++ b/include/scsi/scsi_transport_iscsi.h
@@ -137,6 +137,7 @@ struct iscsi_transport {
 	int (*tgt_dscvr) (struct Scsi_Host *shost, enum iscsi_tgt_dscvr type,
 			  uint32_t enable, struct sockaddr *dst_addr);
 	int (*set_path) (struct Scsi_Host *shost, struct iscsi_path *params);
+	int (*set_iface_param) (struct Scsi_Host *shost, char *data, int count);
 };
 
 /*
-- 
GitLab