Hey offload guys,

If we are using a offload card, then iface_set_param will match the 
iface info to a scsi_host and pass that info down to setup the net 
settings of the port (currently we just set the ip address). When we 
create the tcp/ip connection by calling ep_connect, we currently just go 
by the routing table info.

I think there are two problems with this.

1. Some drivers do not have access to a routing table. Some drivers like 
qla4xxx do not even know about other ports.

2. If you have two initiator ports on the same subnet, the user may have 
set things up so that session1 was supposed to be run through port1. and 
session2 was supposed to be run through port2. It looks like we could 
end with both sessions going through one of the ports.

Also how do you edit the routing table for the offload cards? You cannot 
use normal net tools like route can you?

3. If we set up hostA in the iface_set_param step, but then the routing 
info leads us to hostB, we are stuck.


I did the attached patches to fix this. Basically we just pass down the 
scsi host we want to go through. Well, ok I began to fix this :) For 
qla4xxx or serverengines I think this will work fine.

For bnx2i and cxgb3i, I am not sure. See the TODO and note in cxgb3i in 
kern-ep-connect-through-host.patch. bnx2i guys, you guys do somehting 
similar so will this work? In ep_connect can I control which host/port 
to use?

The patches were made against my iscsi tress. The kernel one was made 
over the iscsi brandh and that was just updated so you might want to 
reclone.

The userspace one was made over the open-iscsi git tree head.

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"open-iscsi" group.
To post to this group, send email to open-iscsi@googlegroups.com
To unsubscribe from this group, send email to 
open-iscsi+unsubscr...@googlegroups.com
For more options, visit this group at http://groups.google.com/group/open-iscsi
-~----------~----~----~----~------~----~------~--~---

diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c 
b/drivers/infiniband/ulp/iser/iscsi_iser.c
index 75223f5..ffbe0c7 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -517,7 +517,8 @@ iscsi_iser_conn_get_stats(struct iscsi_cls_conn *cls_conn, 
struct iscsi_stats *s
 }
 
 static struct iscsi_endpoint *
-iscsi_iser_ep_connect(struct sockaddr *dst_addr, int non_blocking)
+iscsi_iser_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
+                     int non_blocking)
 {
        int err;
        struct iser_conn *ib_conn;
diff --git a/drivers/scsi/cxgb3i/cxgb3i.h b/drivers/scsi/cxgb3i/cxgb3i.h
index 59b0958..e3133b5 100644
--- a/drivers/scsi/cxgb3i/cxgb3i.h
+++ b/drivers/scsi/cxgb3i/cxgb3i.h
@@ -144,7 +144,6 @@ struct cxgb3i_adapter *cxgb3i_adapter_find_by_tdev(struct 
t3cdev *);
 void cxgb3i_adapter_open(struct t3cdev *);
 void cxgb3i_adapter_close(struct t3cdev *);
 
-struct cxgb3i_hba *cxgb3i_hba_find_by_netdev(struct net_device *);
 struct cxgb3i_hba *cxgb3i_hba_host_add(struct cxgb3i_adapter *,
                                       struct net_device *);
 void cxgb3i_hba_host_remove(struct cxgb3i_hba *);
diff --git a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c 
b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
index 9212400..f423c49 100644
--- a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
+++ b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
@@ -178,7 +178,7 @@ void cxgb3i_adapter_close(struct t3cdev *t3dev)
  * cxgb3i_hba_find_by_netdev - find the cxgb3i_hba structure via net_device
  * @t3dev: t3cdev adapter
  */
-struct cxgb3i_hba *cxgb3i_hba_find_by_netdev(struct net_device *ndev)
+static struct cxgb3i_hba *cxgb3i_hba_find_by_netdev(struct net_device *ndev)
 {
        struct cxgb3i_adapter *snic;
        int i;
@@ -261,12 +261,14 @@ void cxgb3i_hba_host_remove(struct cxgb3i_hba *hba)
 
 /**
  * cxgb3i_ep_connect - establish TCP connection to target portal
+ * @shost:             scsi host to use
  * @dst_addr:          target IP address
  * @non_blocking:      blocking or non-blocking call
  *
  * Initiates a TCP/IP connection to the dst_addr
  */
-static struct iscsi_endpoint *cxgb3i_ep_connect(struct sockaddr *dst_addr,
+static struct iscsi_endpoint *cxgb3i_ep_connect(struct Scsi_Host *shost,
+                                               struct sockaddr *dst_addr,
                                                int non_blocking)
 {
        struct iscsi_endpoint *ep;
@@ -275,6 +277,13 @@ static struct iscsi_endpoint *cxgb3i_ep_connect(struct 
sockaddr *dst_addr,
        struct s3_conn *c3cn = NULL;
        int err = 0;
 
+       if (!shost) {
+               cxgb3i_log_error("Cannot connect. Missing host. Check that "
+                                "have the current iscsi tools.\n");
+               err = -EINVAL;
+               goto release_conn;
+       }
+
        c3cn = cxgb3i_c3cn_create();
        if (!c3cn) {
                cxgb3i_log_info("ep connect OOM.\n");
@@ -293,6 +302,19 @@ static struct iscsi_endpoint *cxgb3i_ep_connect(struct 
sockaddr *dst_addr,
                cxgb3i_log_info("NOT going through cxgbi device.\n");
                goto release_conn;
        }
+
+       /*
+        * TODO: If there are multiple routes we want to be able to
+        * select which one to use similar to using the sock opt
+        * SO_BINDTODEVICE.
+        */
+       if (hba != iscsi_host_priv(shost)) {
+               err = -ENOSPC;
+               cxgb3i_log_info("Could not connect through request host%u\n",
+                                shost->host_no);
+               goto release_conn;
+       }
+
        if (c3cn_is_closing(c3cn)) {
                err = -ENOSPC;
                cxgb3i_log_info("ep connect unable to connect.\n");
diff --git a/drivers/scsi/scsi_transport_iscsi.c 
b/drivers/scsi/scsi_transport_iscsi.c
index 0947954..858baff 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -1268,26 +1268,54 @@ iscsi_set_param(struct iscsi_transport *transport, 
struct iscsi_uevent *ev)
        return err;
 }
 
+static int iscsi_if_ep_connect(struct iscsi_transport *transport,
+                              struct iscsi_uevent *ev, int msg_type)
+{
+       struct iscsi_endpoint *ep;
+       struct sockaddr *dst_addr;
+       struct Scsi_Host *shost = NULL;
+       int non_blocking, err = 0;
+
+       if (!transport->ep_connect)
+               return -EINVAL;
+
+       if (msg_type == ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST) {
+               shost = scsi_host_lookup(ev->u.ep_connect_through_host.host_no);
+               if (!shost) {
+                       printk(KERN_ERR "ep connect failed. Could not find "
+                              "host no %u\n",
+                              ev->u.ep_connect_through_host.host_no);
+                       return -ENODEV;
+               }
+               non_blocking = ev->u.ep_connect_through_host.non_blocking;
+       } else
+               non_blocking = ev->u.ep_connect.non_blocking;
+
+       dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev));
+       ep = transport->ep_connect(shost, dst_addr, non_blocking);
+       if (IS_ERR(ep)) {
+               err = PTR_ERR(ep);
+               goto release_host;
+       }
+
+       ev->r.ep_connect_ret.handle = ep->id;
+release_host:
+       if (shost)
+               scsi_host_put(shost);
+       return err;
+}
+
 static int
 iscsi_if_transport_ep(struct iscsi_transport *transport,
                      struct iscsi_uevent *ev, int msg_type)
 {
        struct iscsi_endpoint *ep;
-       struct sockaddr *dst_addr;
        int rc = 0;
 
        switch (msg_type) {
+       case ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST:
        case ISCSI_UEVENT_TRANSPORT_EP_CONNECT:
-               if (!transport->ep_connect)
-                       return -EINVAL;
-
-               dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev));
-               ep = transport->ep_connect(dst_addr,
-                                          ev->u.ep_connect.non_blocking);
-               if (IS_ERR(ep))
-                       return PTR_ERR(ep);
-
-               ev->r.ep_connect_ret.handle = ep->id;
+               rc = iscsi_if_ep_connect(transport, ev, msg_type);
                break;
        case ISCSI_UEVENT_TRANSPORT_EP_POLL:
                if (!transport->ep_poll)
@@ -1469,6 +1497,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr 
*nlh)
        case ISCSI_UEVENT_TRANSPORT_EP_CONNECT:
        case ISCSI_UEVENT_TRANSPORT_EP_POLL:
        case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
+       case ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST:
                err = iscsi_if_transport_ep(transport, ev, nlh->nlmsg_type);
                break;
        case ISCSI_UEVENT_TGT_DSCVR:
diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
index d0ed522..7c76de7 100644
--- a/include/scsi/iscsi_if.h
+++ b/include/scsi/iscsi_if.h
@@ -52,6 +52,8 @@ enum iscsi_uevent_e {
        ISCSI_UEVENT_UNBIND_SESSION     = UEVENT_BASE + 17,
        ISCSI_UEVENT_CREATE_BOUND_SESSION       = UEVENT_BASE + 18,
 
+       ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST  = UEVENT_BASE + 19,
+
        /* up events */
        ISCSI_KEVENT_RECV_PDU           = KEVENT_BASE + 1,
        ISCSI_KEVENT_CONN_ERROR         = KEVENT_BASE + 2,
@@ -131,6 +133,10 @@ struct iscsi_uevent {
                struct msg_transport_connect {
                        uint32_t        non_blocking;
                } ep_connect;
+               struct msg_transport_connect_through_host {
+                       uint32_t        host_no;
+                       uint32_t        non_blocking;
+               } ep_connect_through_host;
                struct msg_transport_poll {
                        uint64_t        ep_handle;
                        uint32_t        timeout_ms;
diff --git a/include/scsi/scsi_transport_iscsi.h 
b/include/scsi/scsi_transport_iscsi.h
index 457588e..8cb7a31 100644
--- a/include/scsi/scsi_transport_iscsi.h
+++ b/include/scsi/scsi_transport_iscsi.h
@@ -126,7 +126,8 @@ struct iscsi_transport {
                               int *index, int *age);
 
        void (*session_recovery_timedout) (struct iscsi_cls_session *session);
-       struct iscsi_endpoint *(*ep_connect) (struct sockaddr *dst_addr,
+       struct iscsi_endpoint *(*ep_connect) (struct Scsi_Host *shost,
+                                             struct sockaddr *dst_addr,
                                              int non_blocking);
        int (*ep_poll) (struct iscsi_endpoint *ep, int timeout_ms);
        void (*ep_disconnect) (struct iscsi_endpoint *ep);
diff --git a/include/iscsi_if.h b/include/iscsi_if.h
index 81f92e8..90841bf 100644
--- a/include/iscsi_if.h
+++ b/include/iscsi_if.h
@@ -52,6 +52,8 @@ enum iscsi_uevent_e {
        ISCSI_UEVENT_UNBIND_SESSION     = UEVENT_BASE + 17,
        ISCSI_UEVENT_CREATE_BOUND_SESSION       = UEVENT_BASE + 18,
 
+       ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST  = UEVENT_BASE + 19,
+
        /* up events */
        ISCSI_KEVENT_RECV_PDU           = KEVENT_BASE + 1,
        ISCSI_KEVENT_CONN_ERROR         = KEVENT_BASE + 2,
@@ -131,6 +133,10 @@ struct iscsi_uevent {
                struct msg_transport_connect {
                        uint32_t        non_blocking;
                } ep_connect;
+               struct msg_transport_connect_through_host {
+                       uint32_t        host_no;
+                       uint32_t        non_blocking;
+               } ep_connect_through_host;
                struct msg_transport_poll {
                        uint64_t        ep_handle;
                        uint32_t        timeout_ms;
diff --git a/usr/initiator.c b/usr/initiator.c
index 8e4ea6b..4a56347 100644
--- a/usr/initiator.c
+++ b/usr/initiator.c
@@ -2074,7 +2074,7 @@ static int iface_set_param(struct iscsi_transport *t, 
struct iface_rec *iface,
        hostno = iscsi_sysfs_get_host_no_from_hwinfo(iface, &rc);
        if (rc)
                return rc;
-
+       session->conn[0].bind_ep = 1;
        session->hostno = hostno;
 
        rc = __iscsi_host_set_param(t, session->hostno,
diff --git a/usr/initiator.h b/usr/initiator.h
index 682ebfc..5bcf4d1 100644
--- a/usr/initiator.h
+++ b/usr/initiator.h
@@ -152,6 +152,7 @@ typedef struct iscsi_conn {
          * transports (eg iser) which does these ops from the kernel.
          * In the case of TCP, it is just the transport_fd casted to u64. */
        uint64_t transport_ep_handle;
+       int bind_ep;
 
        /* timeouts */
        int login_timeout;
diff --git a/usr/netlink.c b/usr/netlink.c
index 9172259..3d697ef 100644
--- a/usr/netlink.c
+++ b/usr/netlink.c
@@ -757,9 +757,17 @@ ktransport_ep_connect(iscsi_conn_t *conn, int non_blocking)
 
        memset(setparam_buf, 0, NLM_SETPARAM_DEFAULT_MAX);
        ev = (struct iscsi_uevent *)setparam_buf;
-       ev->type = ISCSI_UEVENT_TRANSPORT_EP_CONNECT;
        ev->transport_handle = conn->session->t->handle;
 
+       if (conn->bind_ep) {
+               ev->type = ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST;
+               ev->u.ep_connect_through_host.non_blocking = non_blocking;
+               ev->u.ep_connect_through_host.host_no = conn->session->hostno;
+       } else {
+               ev->type = ISCSI_UEVENT_TRANSPORT_EP_CONNECT;
+               ev->u.ep_connect.non_blocking = non_blocking;
+       }
+
        if (dst_addr->sa_family == PF_INET)
                addrlen = sizeof(struct sockaddr_in);
        else if (dst_addr->sa_family == PF_INET6)
@@ -770,7 +778,6 @@ ktransport_ep_connect(iscsi_conn_t *conn, int non_blocking)
                return -EINVAL;
        }
        memcpy(setparam_buf + sizeof(*ev), dst_addr, addrlen);
-       ev->u.ep_connect.non_blocking = non_blocking;
 
        if ((rc = __kipc_call(ev, sizeof(*ev) + addrlen)) < 0)
                return rc;

Reply via email to