commit 86b865b61d530188e3d6a59773ca7edbc8d30767 Author: Hannes Reinecke 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 Signed-off-by: Chandra Seetharaman Signed-off-by: Hannes Reinecke 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