forked from pool/open-iscsi
363 lines
12 KiB
Plaintext
363 lines
12 KiB
Plaintext
|
commit 86b865b61d530188e3d6a59773ca7edbc8d30767
|
||
|
Author: Hannes Reinecke <hare@suse.de>
|
||
|
Date: Thu Nov 20 15:45:02 2008 +0100
|
||
|
|
||
|
cxgb3 iSCSI TOE support
|
||
|
|
||
|
This patch enable cxgb3i iSCSI TOE support for open-iscsi.
|
||
|
|
||
|
References: bnc#433500, FATE#304154
|
||
|
|
||
|
Signed-off-by: Karen Xie <kxie@chelsio.com>
|
||
|
Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com>
|
||
|
Signed-off-by: Hannes Reinecke <hare@suse.de>
|
||
|
|
||
|
diff --git a/doc/iscsiadm.8 b/doc/iscsiadm.8
|
||
|
index b488ad5..8fe14d4 100644
|
||
|
--- a/doc/iscsiadm.8
|
||
|
+++ b/doc/iscsiadm.8
|
||
|
@@ -63,10 +63,10 @@ specific hardware resource and instead allow the network or infinniband layer
|
||
|
to decide what to do. There is no need to create a iface config with the default
|
||
|
behavior. If you do not specify a iface, then the default behavior is used.
|
||
|
|
||
|
-As mentioned above there is a special iface name default. There are two others
|
||
|
-bnx2i and iser, which does not bind the session to a specific card, but
|
||
|
-will bind the session to either the bnx2i or iser transport. These are
|
||
|
-experimental and the use is not supported as a stable interface yet.
|
||
|
+As mentioned above there is a special iface name default. There are three
|
||
|
+others -- cxgb3i, bnx2i and iser, which does not bind the session to a specific
|
||
|
+card, but will bind the session to the cxgb3i, bnx2i or iser transport. These
|
||
|
+are experimental and the use is not supported as a stable interface yet.
|
||
|
|
||
|
In discovery mode multiple interfaces can be specific by passing in multiple
|
||
|
-I/--interface instances. For example,
|
||
|
diff --git a/etc/iface.example b/etc/iface.example
|
||
|
index 7fb7951..020b002 100644
|
||
|
--- a/etc/iface.example
|
||
|
+++ b/etc/iface.example
|
||
|
@@ -20,6 +20,7 @@
|
||
|
# - iser (Software iSCSI over infinniband
|
||
|
# - qla4xxx (Qlogic QLA4XXX HBAs)
|
||
|
# - bnx2i (Broadcom bnx iSCSI HBAs);
|
||
|
+# - cxgb3i (Chelsio cxgb S3 iSCSI HBAs);
|
||
|
#
|
||
|
#OPTIONAL: iface.initiatorname
|
||
|
# To use a initiator name other than the one set in
|
||
|
@@ -51,3 +52,13 @@
|
||
|
|
||
|
# Note you can only bind using one value. If you set multiple values
|
||
|
# the bahavior is not defined.
|
||
|
+
|
||
|
+# For some transport (cxgb3i), a user could to set the private ip address for
|
||
|
+# the iscsi traffic for an network interface:
|
||
|
+# example:
|
||
|
+# - set iscsi ip on eth0 to be 102.50.50.101, eth0 needs to be up and be on
|
||
|
+# the same subnet.
|
||
|
+# iface.net_ifacename = eth0
|
||
|
+# iface.ipaddress = 102.50.50.101
|
||
|
+~
|
||
|
+
|
||
|
diff --git a/usr/idbm.c b/usr/idbm.c
|
||
|
index a7a1072..6f4ed12 100644
|
||
|
--- a/usr/idbm.c
|
||
|
+++ b/usr/idbm.c
|
||
|
@@ -274,8 +274,8 @@ idbm_recinfo_node(node_rec_t *r, recinfo_t *ri)
|
||
|
*/
|
||
|
__recinfo_str("iface.hwaddress", ri, r, iface.hwaddress, IDBM_SHOW,
|
||
|
num, 1);
|
||
|
-// __recinfo_str("iface.ipaddress", ri, r, iface.ipaddress,
|
||
|
-// IDBM_SHOW, num);
|
||
|
+ __recinfo_str("iface.ipaddress", ri, r, iface.ipaddress, IDBM_SHOW,
|
||
|
+ num, 1);
|
||
|
__recinfo_str("iface.iscsi_ifacename", ri, r, iface.name, IDBM_SHOW,
|
||
|
num, 1);
|
||
|
__recinfo_str("iface.net_ifacename", ri, r, iface.netdev, IDBM_SHOW,
|
||
|
@@ -413,7 +413,7 @@ void idbm_recinfo_iface(iface_rec_t *r, recinfo_t *ri)
|
||
|
|
||
|
__recinfo_str("iface.iscsi_ifacename", ri, r, name, IDBM_SHOW, num, 0);
|
||
|
__recinfo_str("iface.net_ifacename", ri, r, netdev, IDBM_SHOW, num, 1);
|
||
|
-// __recinfo_str("iface.ipaddress", ri, r, ipaddress, IDBM_SHOW, num, 1);
|
||
|
+ __recinfo_str("iface.ipaddress", ri, r, ipaddress, IDBM_SHOW, num, 1);
|
||
|
__recinfo_str("iface.hwaddress", ri, r, hwaddress, IDBM_SHOW, num, 1);
|
||
|
__recinfo_str("iface.transport_name", ri, r, transport_name,
|
||
|
IDBM_SHOW, num, 1);
|
||
|
diff --git a/usr/iface.c b/usr/iface.c
|
||
|
index 01b87da..3273197 100644
|
||
|
--- a/usr/iface.c
|
||
|
+++ b/usr/iface.c
|
||
|
@@ -104,7 +104,7 @@ static void iface_init(struct iface_rec *iface)
|
||
|
void iface_setup_defaults(struct iface_rec *iface)
|
||
|
{
|
||
|
sprintf(iface->netdev, DEFAULT_NETDEV);
|
||
|
-// sprintf(iface->ipaddress, DEFAULT_IPADDRESS);
|
||
|
+ sprintf(iface->ipaddress, DEFAULT_IPADDRESS);
|
||
|
sprintf(iface->hwaddress, DEFAULT_HWADDRESS);
|
||
|
sprintf(iface->transport_name, DEFAULT_TRANSPORT);
|
||
|
iface_init(iface);
|
||
|
@@ -494,8 +494,8 @@ void iface_copy(struct iface_rec *dst, struct iface_rec *src)
|
||
|
strcpy(dst->name, src->name);
|
||
|
if (strlen(src->netdev))
|
||
|
strcpy(dst->netdev, src->netdev);
|
||
|
-// if (strlen(src->ipaddress))
|
||
|
-// strcpy(dst->ipaddress, src->ipaddress);
|
||
|
+ if (strlen(src->ipaddress))
|
||
|
+ strcpy(dst->ipaddress, src->ipaddress);
|
||
|
if (strlen(src->hwaddress))
|
||
|
strcpy(dst->hwaddress, src->hwaddress);
|
||
|
if (strlen(src->transport_name))
|
||
|
@@ -594,6 +594,8 @@ int iface_print_tree(void *data, struct iface_rec *iface)
|
||
|
UNKNOWN_VALUE);
|
||
|
printf("\tHW Address: %s\n",
|
||
|
strlen(iface->hwaddress) ? iface->hwaddress : UNKNOWN_VALUE);
|
||
|
+ printf("\tIP Address: %s\n",
|
||
|
+ strlen(iface->ipaddress) ? iface->ipaddress : UNKNOWN_VALUE);
|
||
|
printf("\tNetdev: %s\n",
|
||
|
strlen(iface->netdev) ? iface->netdev : UNKNOWN_VALUE);
|
||
|
printf("\tInitiator Name: %s\n",
|
||
|
@@ -603,11 +605,12 @@ int iface_print_tree(void *data, struct iface_rec *iface)
|
||
|
|
||
|
int iface_print_flat(void *data, struct iface_rec *iface)
|
||
|
{
|
||
|
- printf("%s %s,%s,%s,%s\n",
|
||
|
+ printf("%s %s,%s,%s,%s,%s\n",
|
||
|
strlen(iface->name) ? iface->name : UNKNOWN_VALUE,
|
||
|
strlen(iface->transport_name) ? iface->transport_name :
|
||
|
UNKNOWN_VALUE,
|
||
|
strlen(iface->hwaddress) ? iface->hwaddress : UNKNOWN_VALUE,
|
||
|
+ strlen(iface->ipaddress) ? iface->ipaddress : UNKNOWN_VALUE,
|
||
|
strlen(iface->netdev) ? iface->netdev : UNKNOWN_VALUE,
|
||
|
strlen(iface->iname) ? iface->iname : UNKNOWN_VALUE);
|
||
|
return 0;
|
||
|
diff --git a/usr/initiator.c b/usr/initiator.c
|
||
|
index 10cf050..8e95841 100644
|
||
|
--- a/usr/initiator.c
|
||
|
+++ b/usr/initiator.c
|
||
|
@@ -1176,7 +1176,7 @@ mgmt_ipc_err_e iscsi_host_set_param(int host_no, int param, char *value)
|
||
|
return MGMT_IPC_OK;
|
||
|
}
|
||
|
|
||
|
-#define MAX_SESSION_PARAMS 30
|
||
|
+#define MAX_SESSION_PARAMS 31
|
||
|
#define MAX_HOST_PARAMS 3
|
||
|
|
||
|
static void
|
||
|
@@ -1360,6 +1360,10 @@ setup_full_feature_phase(iscsi_conn_t *conn)
|
||
|
.param = ISCSI_PARAM_IFACE_NAME,
|
||
|
.value = session->nrec.iface.name,
|
||
|
.type = ISCSI_STRING,
|
||
|
+ }, {
|
||
|
+ .param = ISCSI_PARAM_INITIATOR_NAME,
|
||
|
+ .value = session->initiator_name,
|
||
|
+ .type = ISCSI_STRING,
|
||
|
},
|
||
|
};
|
||
|
|
||
|
@@ -1946,6 +1950,54 @@ int session_is_running(node_rec_t *rec)
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
+static int iface_set_param(struct iscsi_transport *t, iface_rec_t *iface,
|
||
|
+ iscsi_session_t *session)
|
||
|
+{
|
||
|
+ int rc = 0;
|
||
|
+ int netdev_set = strcasecmp(iface->netdev, DEFAULT_NETDEV);
|
||
|
+ int ipaddr_set = strcasecmp(iface->ipaddress, DEFAULT_IPADDRESS);
|
||
|
+ int hwaddr_set = strcasecmp(iface->hwaddress, DEFAULT_HWADDRESS);
|
||
|
+ int hostno;
|
||
|
+ iface_rec_t *iface_tmp;
|
||
|
+
|
||
|
+ log_debug(3, "iface %s, dev %s, set ip %s, hw %s, tranport %s.\n",
|
||
|
+ iface->name, iface->netdev, iface->ipaddress,
|
||
|
+ iface->hwaddress, iface->transport_name);
|
||
|
+
|
||
|
+ /* proceed only when netdev and either ipaddress or hwaddress is set */
|
||
|
+ if (!netdev_set || (!ipaddr_set && !hwaddr_set))
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ /* find out hostno via netdev */
|
||
|
+ iface_tmp = calloc(1, sizeof(*iface_tmp));
|
||
|
+ strcpy(iface_tmp->netdev, iface->netdev);
|
||
|
+ hostno = iscsi_sysfs_get_host_no_from_iface(iface_tmp, &rc);
|
||
|
+ free(iface_tmp);
|
||
|
+ if (rc)
|
||
|
+ return rc;
|
||
|
+ session->hostno = hostno;
|
||
|
+
|
||
|
+ if (ipaddr_set) {
|
||
|
+ rc = __iscsi_host_set_param(t, session->hostno,
|
||
|
+ ISCSI_HOST_PARAM_IPADDRESS,
|
||
|
+ iface->ipaddress,
|
||
|
+ ISCSI_STRING);
|
||
|
+ if (rc)
|
||
|
+ return rc;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (hwaddr_set) {
|
||
|
+ rc = __iscsi_host_set_param(t, session->hostno,
|
||
|
+ ISCSI_HOST_PARAM_HWADDRESS,
|
||
|
+ iface->hwaddress,
|
||
|
+ ISCSI_STRING);
|
||
|
+ if (rc)
|
||
|
+ return rc;
|
||
|
+ }
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
int
|
||
|
session_login_task(node_rec_t *rec, queue_task_t *qtask)
|
||
|
{
|
||
|
@@ -2028,6 +2080,11 @@ session_login_task(node_rec_t *rec, queue_task_t *qtask)
|
||
|
conn = &session->conn[0];
|
||
|
qtask->conn = conn;
|
||
|
|
||
|
+ if (iface_set_param(t, &rec->iface, session)) {
|
||
|
+ __session_destroy(session);
|
||
|
+ return MGMT_IPC_ERR_LOGIN_FAILURE;
|
||
|
+ }
|
||
|
+
|
||
|
conn->state = STATE_XPT_WAIT;
|
||
|
if (iscsi_conn_connect(conn, qtask)) {
|
||
|
__session_destroy(session);
|
||
|
diff --git a/usr/iscsi_sysfs.c b/usr/iscsi_sysfs.c
|
||
|
index cab3ec1..54b6ee6 100644
|
||
|
--- a/usr/iscsi_sysfs.c
|
||
|
+++ b/usr/iscsi_sysfs.c
|
||
|
@@ -531,7 +531,7 @@ uint32_t iscsi_sysfs_get_host_no_from_iface(struct iface_rec *iface, int *rc)
|
||
|
else if (strlen(iface->ipaddress) &&
|
||
|
strcasecmp(iface->ipaddress, DEFAULT_IPADDRESS))
|
||
|
host_no = get_host_no_from_ipaddress(iface->ipaddress, &tmp_rc);
|
||
|
- else if(strlen(iface->netdev) &&
|
||
|
+ else if (strlen(iface->netdev) &&
|
||
|
strcasecmp(iface->netdev, DEFAULT_NETDEV))
|
||
|
host_no = get_host_no_from_netdev(iface->netdev, &tmp_rc);
|
||
|
else
|
||
|
@@ -582,35 +582,78 @@ static int sysfs_read_iface(struct iface_rec *iface, int host_no, int sid)
|
||
|
log_debug(7, "could not read netdev for host%d\n", host_no);
|
||
|
}
|
||
|
|
||
|
- ret = iscsi_sysfs_get_iscsi_host_param(host_no, "initiatorname",
|
||
|
- iface->iname, "%s\n");
|
||
|
- if (ret)
|
||
|
- /* default iname is picked up later from initiatorname.iscsi */
|
||
|
- log_debug(7, "Could not read initiatorname for host%d\n",
|
||
|
- host_no);
|
||
|
-
|
||
|
/*
|
||
|
- * this is on the session, because we support multiple bindings
|
||
|
- * per device.
|
||
|
+ * If we are looping over the hosts then we want to read the
|
||
|
+ * initiator name set at that level instead of the session
|
||
|
+ * level one, because if we created a iscsi port with a different
|
||
|
+ * iname then they will not match.
|
||
|
*/
|
||
|
- memset(iface->name, 0, sizeof(iface->name));
|
||
|
- /*
|
||
|
- * this was added after 2.0.869 so we could be doing iscsi_tcp
|
||
|
- * session binding, but there may not be a ifacename set
|
||
|
- */
|
||
|
- ret = iscsi_sysfs_get_session_param(sid, "ifacename", iface->name,
|
||
|
- "%s\n");
|
||
|
+ ret = 1;
|
||
|
+ if (sid != -1) {
|
||
|
+ /*
|
||
|
+ * this is on the session, because we support multiple bindings
|
||
|
+ * per device.
|
||
|
+ */
|
||
|
+ memset(iface->name, 0, sizeof(iface->name));
|
||
|
+ /*
|
||
|
+ * this was added after 2.0.869 so we could be doing iscsi_tcp
|
||
|
+ * session binding, but there may not be a ifacename set
|
||
|
+ */
|
||
|
+ ret = iscsi_sysfs_get_session_param(sid, "ifacename",
|
||
|
+ iface->name, "%s\n");
|
||
|
+ /* if failed then look ifacename through binding tuple */
|
||
|
+ if (ret)
|
||
|
+ log_debug(7, "could not read iface name for sid %u\n",
|
||
|
+ sid);
|
||
|
+ }
|
||
|
+
|
||
|
if (ret) {
|
||
|
- log_debug(7, "could not read iface name for sid %u\n", sid);
|
||
|
/*
|
||
|
- * if the ifacename file is not there then we are using a older
|
||
|
- * kernel and can try to find the binding by the net info
|
||
|
- * which was used on these older kernels.
|
||
|
- */
|
||
|
+ * if the ifacename file (will always not be for qla4xxx)
|
||
|
+ * is not there then we are using a older kernel and can
|
||
|
+ * try to find the binding by the net info which was
|
||
|
+ * used on these older kernels. If scanning hosts then
|
||
|
+ * we must go this route currently because we do not
|
||
|
+ * store the ifacename on the host for qla4xxx.
|
||
|
+ */
|
||
|
if (iface_get_by_net_binding(iface, iface))
|
||
|
- log_debug(7, "Could not find iface for session bound "
|
||
|
- "to:" iface_fmt "\n", iface_str(iface));
|
||
|
+ log_debug(7, "Could not find iface for "
|
||
|
+ "session bound to:" iface_fmt "\n",
|
||
|
+ iface_str(iface));
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = 1;
|
||
|
+ if (sid != 1) {
|
||
|
+ /*
|
||
|
+ * 2.0.870 we added the two inames to distinguish
|
||
|
+ * between one that may be set at the hba level
|
||
|
+ * as the default and one that we set for the iface
|
||
|
+ * so we could create a virtual initiator port.
|
||
|
+ */
|
||
|
+ ret = iscsi_sysfs_get_session_param(sid, "initiatorname",
|
||
|
+ iface->iname, "%s\n");
|
||
|
+ if (ret)
|
||
|
+ /*
|
||
|
+ * default iname is picked up later from
|
||
|
+ * initiatorname.iscsi
|
||
|
+ */
|
||
|
+ log_debug(7, "Could not read initiatorname for "
|
||
|
+ "host%d\n", host_no);
|
||
|
+ /* drop through to older iface iname */
|
||
|
}
|
||
|
+
|
||
|
+ if (ret) {
|
||
|
+ ret = iscsi_sysfs_get_iscsi_host_param(host_no, "initiatorname",
|
||
|
+ iface->iname, "%s\n");
|
||
|
+ if (ret)
|
||
|
+ /*
|
||
|
+ * default iname is picked up later from
|
||
|
+ * initiatorname.iscsi
|
||
|
+ */
|
||
|
+ log_debug(7, "Could not read initiatorname for "
|
||
|
+ "host%d\n", host_no);
|
||
|
+ }
|
||
|
+
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
diff --git a/usr/transport.c b/usr/transport.c
|
||
|
index c2edbcc..07b61db 100644
|
||
|
--- a/usr/transport.c
|
||
|
+++ b/usr/transport.c
|
||
|
@@ -41,6 +41,13 @@ struct iscsi_transport_template iscsi_iser = {
|
||
|
.ep_disconnect = ktransport_ep_disconnect,
|
||
|
};
|
||
|
|
||
|
+struct iscsi_transport_template cxgb3i = {
|
||
|
+ .name = "cxgb3i",
|
||
|
+ .ep_connect = ktransport_ep_connect,
|
||
|
+ .ep_poll = ktransport_ep_poll,
|
||
|
+ .ep_disconnect = ktransport_ep_disconnect,
|
||
|
+};
|
||
|
+
|
||
|
struct iscsi_transport_template bnx2i = {
|
||
|
.name = "bnx2i",
|
||
|
.ep_connect = ktransport_ep_connect,
|
||
|
@@ -55,6 +62,7 @@ struct iscsi_transport_template qla4xxx = {
|
||
|
static struct iscsi_transport_template *iscsi_transport_templates[] = {
|
||
|
&iscsi_tcp,
|
||
|
&iscsi_iser,
|
||
|
+ &cxgb3i,
|
||
|
&bnx2i,
|
||
|
&qla4xxx,
|
||
|
NULL
|