From: Adheer Chandravanshi <adheer.chandravan...@qlogic.com>

These changes are done in order to support ping operation for drivers
like bnx2i that use iscsiuio.

Signed-off-by: Adheer Chandravanshi <adheer.chandravan...@qlogic.com>
---
 usr/iscsiadm.c     |   29 +++++++++++++++++++++++------
 usr/iscsid_req.c   |   38 +++++++++++++++++++++++++++++++++-----
 usr/iscsid_req.h   |    2 +-
 usr/transport.c    |    1 +
 usr/transport.h    |    3 +++
 usr/uip_mgmt_ipc.c |   38 +++++++++++++++++++++++++++++++++++++-
 usr/uip_mgmt_ipc.h |   13 +++++++++++++
 7 files changed, 111 insertions(+), 13 deletions(-)

diff --git a/usr/iscsiadm.c b/usr/iscsiadm.c
index 6f96755..bb86d21 100644
--- a/usr/iscsiadm.c
+++ b/usr/iscsiadm.c
@@ -3114,10 +3114,10 @@ static char *iscsi_ping_stat_strs[] = {
        "No ARP response received",
 };
 
-static char *iscsi_ping_stat_to_str(uint32_t status)
+static char *iscsi_ping_stat_to_str(int status)
 {
        if (status < 0 || status > ISCSI_PING_NO_ARP_RECEIVED) {
-               log_error("Invalid ping status %u\n", status);
+               log_error("Ping error: %s\n", strerror(status));
                return NULL;
        }
 
@@ -3130,8 +3130,10 @@ static int exec_ping_op(struct iface_rec *iface, char 
*ip, int size, int count,
        int rc = ISCSI_ERR;
        uint32_t iface_type = ISCSI_IFACE_TYPE_IPV4;
        struct iscsi_transport *t = NULL;
-       uint32_t host_no, status = 0;
+       uint32_t host_no;
+       int status = 0;
        struct sockaddr_storage addr;
+       struct host_info hinfo;
        int i;
 
        if (!iface) {
@@ -3200,12 +3202,27 @@ static int exec_ping_op(struct iface_rec *iface, char 
*ip, int size, int count,
        for (i = 1; i <= count; i++) {
                /*
                 * To support drivers like bnx2i that do not use
-                * the iscsi if to send a ping, we can add a transport
+                * the iscsi iface to send a ping, we invoke transport
                 * callout here.
                 */
                status = 0;
-               rc = ipc->exec_ping(t->handle, host_no, &addr, iface->iface_num,
-                                   iface_type, size, &status);
+               if (t->template->send_ping) {
+                       if (!strlen(iface->netdev)) {
+                               memset(&hinfo, 0, sizeof(hinfo));
+                               hinfo.host_no = host_no;
+                               iscsi_sysfs_get_hostinfo_by_host_no(&hinfo);
+                               strcpy(iface->netdev, hinfo.iface.netdev);
+                       }
+                       rc = t->template->send_ping(t, iface, size, &addr,
+                                                   &status);
+                       if (rc)
+                               rc = ISCSI_ERR_INTERNAL;
+               } else {
+                       rc = ipc->exec_ping(t->handle, host_no, &addr,
+                                           iface->iface_num, iface_type,
+                                           size, (uint32_t *)&status);
+               }
+
                if (!rc && !status)
                        printf("Ping %d completed\n", i);
                else if (status)
diff --git a/usr/iscsid_req.c b/usr/iscsid_req.c
index 0e91dee..f19d194 100644
--- a/usr/iscsid_req.c
+++ b/usr/iscsid_req.c
@@ -203,7 +203,7 @@ static int uip_connect(int *fd)
        return ipc_connect(fd, ISCSID_UIP_NAMESPACE, 0);
 }
 
-int uip_broadcast(void *buf, size_t buf_len)
+int uip_broadcast(void *buf, size_t buf_len, int fd_flags, int *status)
 {
        int err;
        int fd;
@@ -235,7 +235,11 @@ int uip_broadcast(void *buf, size_t buf_len)
        flags = fcntl(fd, F_GETFL, 0);
        if (flags == -1)
                flags = 0;
-       err = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+
+       if (fd_flags)
+               flags |= fd_flags;
+
+       err = fcntl(fd, F_SETFL, flags);
        if (err) {
                log_error("could not set uip broadcast to non-blocking: %d",
                          errno);
@@ -268,11 +272,35 @@ int uip_broadcast(void *buf, size_t buf_len)
                log_error("Could not broadcast to uIP after %d tries",
                          count);
                err = ISCSI_ERR_AGAIN;
-       } else if (rsp.err != ISCSID_UIP_MGMT_IPC_DEVICE_UP) {
-               log_debug(3, "Device is not ready\n");
-               err = ISCSI_ERR_AGAIN;
        }
 
+       if (err)
+               goto done;
+
+       switch (rsp.command) {
+       case ISCSID_UIP_IPC_GET_IFACE:
+               if (rsp.err != ISCSID_UIP_MGMT_IPC_DEVICE_UP) {
+                       log_debug(3, "Device is not ready\n");
+                       err = ISCSI_ERR_AGAIN;
+               }
+
+               break;
+       case ISCSID_UIP_IPC_PING:
+               *status = rsp.ping_sc;
+               if (rsp.err != ISCSID_UIP_MGMT_IPC_DEVICE_UP ||
+                   *status == -EAGAIN) {
+                       log_debug(3, "Device is not ready\n");
+                       err = ISCSI_ERR_AGAIN;
+               } else if (*status) {
+                       err = ISCSI_ERR;
+               }
+
+               break;
+       default:
+               err = ISCSI_ERR;
+       }
+
+done:
        close(fd);
        return err;
 }
diff --git a/usr/iscsid_req.h b/usr/iscsid_req.h
index 4fff43d..32a102f 100644
--- a/usr/iscsid_req.h
+++ b/usr/iscsid_req.h
@@ -33,6 +33,6 @@ extern int iscsid_req_by_rec(int cmd, struct node_rec *rec);
 extern int iscsid_req_by_sid_async(int cmd, int sid, int *fd);
 extern int iscsid_req_by_sid(int cmd, int sid);
 
-extern int uip_broadcast(void *buf, size_t buf_len);
+extern int uip_broadcast(void *buf, size_t buf_len, int fd_flags, int *status);
 
 #endif
diff --git a/usr/transport.c b/usr/transport.c
index e778a6e..7063639 100644
--- a/usr/transport.c
+++ b/usr/transport.c
@@ -85,6 +85,7 @@ struct iscsi_transport_template bnx2i = {
        .ep_poll        = ktransport_ep_poll,
        .ep_disconnect  = ktransport_ep_disconnect,
        .set_net_config = uip_broadcast_params,
+       .send_ping      = uip_broadcast_ping_req,
 };
 
 struct iscsi_transport_template be2iscsi = {
diff --git a/usr/transport.h b/usr/transport.h
index 831403b..0f7039a 100644
--- a/usr/transport.h
+++ b/usr/transport.h
@@ -46,6 +46,9 @@ struct iscsi_transport_template {
        int (*set_net_config) (struct iscsi_transport *t,
                               struct iface_rec *iface,
                               struct iscsi_session *session);
+       int (*send_ping) (struct iscsi_transport *t,
+                         struct iface_rec *iface, int datalen,
+                         struct sockaddr_storage *dst_addr, int *status);
 };
 
 /* represents data path provider */
diff --git a/usr/uip_mgmt_ipc.c b/usr/uip_mgmt_ipc.c
index f3074ee..b2f9470 100644
--- a/usr/uip_mgmt_ipc.c
+++ b/usr/uip_mgmt_ipc.c
@@ -15,6 +15,7 @@
  */
 
 #include <string.h>
+#include <fcntl.h>
 
 #include "log.h"
 #include "uip_mgmt_ipc.h"
@@ -37,5 +38,40 @@ int uip_broadcast_params(struct iscsi_transport *t,
 
        return uip_broadcast(&broadcast,
                             sizeof(iscsid_uip_broadcast_header_t) +
-                            sizeof(*iface));
+                            sizeof(*iface), O_NONBLOCK, NULL);
+}
+
+int uip_broadcast_ping_req(struct iscsi_transport *t,
+                          struct iface_rec *iface, int datalen,
+                          struct sockaddr_storage *dst_addr, int *status)
+{
+       struct iscsid_uip_broadcast broadcast;
+       int len = 0;
+
+       log_debug(3, "broadcasting ping request to uip\n");
+
+       memset(&broadcast, 0, sizeof(broadcast));
+
+       broadcast.header.command = ISCSID_UIP_IPC_PING;
+       len = sizeof(*iface) + sizeof(*dst_addr) + sizeof(datalen);
+       broadcast.header.payload_len = len;
+
+       memcpy(&broadcast.u.ping_rec.ifrec, iface, sizeof(*iface));
+
+       if (dst_addr->ss_family == PF_INET) {
+               len = sizeof(struct sockaddr_in);
+       } else if (dst_addr->ss_family == PF_INET6) {
+               len = sizeof(struct sockaddr_in6);
+       } else {
+               log_error("%s unknown addr family %d\n",
+                         __FUNCTION__, dst_addr->ss_family);
+               return 1;
+       }
+
+       memcpy(&broadcast.u.ping_rec.ipaddr, dst_addr, len);
+       broadcast.u.ping_rec.datalen = datalen;
+
+       return uip_broadcast(&broadcast,
+                            sizeof(iscsid_uip_broadcast_header_t) +
+                            broadcast.header.payload_len, 0, status);
 }
diff --git a/usr/uip_mgmt_ipc.h b/usr/uip_mgmt_ipc.h
index 29a4769..2b95475 100644
--- a/usr/uip_mgmt_ipc.h
+++ b/usr/uip_mgmt_ipc.h
@@ -29,6 +29,7 @@
 typedef enum iscsid_uip_cmd {
        ISCSID_UIP_IPC_UNKNOWN                  = 0,
        ISCSID_UIP_IPC_GET_IFACE                = 1,
+       ISCSID_UIP_IPC_PING                     = 2,
 
        __ISCSID_UIP_IPC_MAX_COMMAND
 } iscsid_uip_cmd_e;
@@ -47,6 +48,13 @@ typedef struct iscsid_uip_broadcast {
                struct ipc_broadcast_iface_rec {
                        struct iface_rec rec;
                } iface_rec;
+
+               struct ipc_broadcast_ping_rec {
+                       struct iface_rec ifrec;
+                       struct sockaddr_storage ipaddr;
+                       int datalen;
+                       int *status;
+               } ping_rec;
        } u;
 } iscsid_uip_broadcast_t;
 
@@ -63,11 +71,16 @@ typedef enum iscsid_uip_mgmt_ipc_err {
 typedef struct iscsid_uip_mgmt_rsp {
        iscsid_uip_cmd_e command;
        iscsid_uip_mgmt_ipc_err_e err;
+       enum iscsi_ping_status_code ping_sc;
 } iscsid_uip_rsp_t;
 
 extern int uip_broadcast_params(struct iscsi_transport *t,
                                struct iface_rec *iface,
                                struct iscsi_session *session);
 
+extern int uip_broadcast_ping_req(struct iscsi_transport *t,
+                                 struct iface_rec *iface, int datalen,
+                                 struct sockaddr_storage *dst_addr,
+                                 int *status);
 
 #endif /* UIP_MGMT_IPC_H */
-- 
1.7.1

-- 
You received this message because you are subscribed to the Google Groups 
"open-iscsi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to open-iscsi+unsubscr...@googlegroups.com.
To post to this group, send email to open-iscsi@googlegroups.com.
Visit this group at http://groups.google.com/group/open-iscsi.
For more options, visit https://groups.google.com/d/optout.

Reply via email to