open-iscsi/open-iscsi-cxgb3i-support

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