Author: trasz
Date: Thu Feb  5 06:37:59 2015
New Revision: 278232
URL: https://svnweb.freebsd.org/changeset/base/278232

Log:
  Make it possible to set (via iscsi.conf(5)) and query (via iscsictl -v)
  initiator iSCSI offload.  Pass maximum data segment size supported by
  chosen offload module to iscsid(8), and make iscsid(8) not try to negotiate
  anything larger than that.
  
  MFC after:    1 month
  Sponsored by: The FreeBSD Foundation

Modified:
  head/sys/dev/iscsi/icl.h
  head/sys/dev/iscsi/icl_soft.c
  head/sys/dev/iscsi/iscsi.c
  head/sys/dev/iscsi/iscsi_ioctl.h
  head/usr.bin/iscsictl/iscsi.conf.5
  head/usr.bin/iscsictl/iscsictl.c
  head/usr.bin/iscsictl/iscsictl.h
  head/usr.bin/iscsictl/parse.y
  head/usr.bin/iscsictl/token.l
  head/usr.sbin/iscsid/iscsid.c
  head/usr.sbin/iscsid/iscsid.h
  head/usr.sbin/iscsid/login.c

Modified: head/sys/dev/iscsi/icl.h
==============================================================================
--- head/sys/dev/iscsi/icl.h    Thu Feb  5 03:56:49 2015        (r278231)
+++ head/sys/dev/iscsi/icl.h    Thu Feb  5 06:37:59 2015        (r278232)
@@ -113,6 +113,7 @@ struct icl_conn {
        bool                    ic_disconnecting;
        bool                    ic_iser;
        const char              *ic_name;
+       const char              *ic_offload;
 
        void                    (*ic_receive)(struct icl_pdu *);
        void                    (*ic_error)(struct icl_conn *);

Modified: head/sys/dev/iscsi/icl_soft.c
==============================================================================
--- head/sys/dev/iscsi/icl_soft.c       Thu Feb  5 03:56:49 2015        
(r278231)
+++ head/sys/dev/iscsi/icl_soft.c       Thu Feb  5 06:37:59 2015        
(r278232)
@@ -1185,6 +1185,7 @@ icl_soft_new_conn(const char *name, stru
 #endif
        ic->ic_max_data_segment_length = ICL_MAX_DATA_SEGMENT_LENGTH;
        ic->ic_name = name;
+       ic->ic_offload = "none";
 
        return (ic);
 }

Modified: head/sys/dev/iscsi/iscsi.c
==============================================================================
--- head/sys/dev/iscsi/iscsi.c  Thu Feb  5 03:56:49 2015        (r278231)
+++ head/sys/dev/iscsi/iscsi.c  Thu Feb  5 06:37:59 2015        (r278232)
@@ -1306,6 +1306,16 @@ iscsi_ioctl_daemon_wait(struct iscsi_sof
                request->idr_tsih = 0;  /* New or reinstated session. */
                memcpy(&request->idr_conf, &is->is_conf,
                    sizeof(request->idr_conf));
+               
+               error = icl_limits(is->is_conf.isc_offload,
+                   &request->idr_limits.isl_max_data_segment_length);
+               if (error != 0) {
+                       ISCSI_SESSION_WARN(is, "icl_limits for offload \"%s\" "
+                           "failed with error %d", is->is_conf.isc_offload,
+                           error);
+                       sx_sunlock(&sc->sc_lock);
+                       return (error);
+               }
 
                sx_sunlock(&sc->sc_lock);
                return (0);
@@ -1731,7 +1741,13 @@ iscsi_ioctl_session_add(struct iscsi_sof
                return (EBUSY);
        }
 
-       is->is_conn = icl_new_conn(NULL, "iscsi", &is->is_lock);
+       is->is_conn = icl_new_conn(is->is_conf.isc_offload,
+           "iscsi", &is->is_lock);
+       if (is->is_conn == NULL) {
+               sx_xunlock(&sc->sc_lock);
+               free(is, M_ISCSI);
+               return (EINVAL);
+       }
        is->is_conn->ic_receive = iscsi_receive_callback;
        is->is_conn->ic_error = iscsi_error_callback;
        is->is_conn->ic_prv0 = is;
@@ -1836,6 +1852,7 @@ iscsi_ioctl_session_list(struct iscsi_so
                iss.iss_id = is->is_id;
                strlcpy(iss.iss_target_alias, is->is_target_alias, 
sizeof(iss.iss_target_alias));
                strlcpy(iss.iss_reason, is->is_reason, sizeof(iss.iss_reason));
+               strlcpy(iss.iss_offload, is->is_conn->ic_offload, 
sizeof(iss.iss_offload));
 
                if (is->is_conn->ic_header_crc32c)
                        iss.iss_header_digest = ISCSI_DIGEST_CRC32C;

Modified: head/sys/dev/iscsi/iscsi_ioctl.h
==============================================================================
--- head/sys/dev/iscsi/iscsi_ioctl.h    Thu Feb  5 03:56:49 2015        
(r278231)
+++ head/sys/dev/iscsi/iscsi_ioctl.h    Thu Feb  5 06:37:59 2015        
(r278232)
@@ -43,6 +43,7 @@
 #define        ISCSI_ADDR_LEN          47      /* INET6_ADDRSTRLEN + '\0' */
 #define        ISCSI_ALIAS_LEN         256     /* XXX: Where did it come from? 
*/
 #define        ISCSI_SECRET_LEN        17      /* 16 + '\0' */
+#define        ISCSI_OFFLOAD_LEN       8
 #define        ISCSI_REASON_LEN        64
 
 #define        ISCSI_DIGEST_NONE       0
@@ -65,7 +66,16 @@ struct iscsi_session_conf {
        int             isc_header_digest;
        int             isc_data_digest;
        int             isc_iser;
-       int             isc_spare[4];
+       char            isc_offload[ISCSI_OFFLOAD_LEN];
+       int             isc_spare[2];
+};
+
+/*
+ * Additional constraints imposed by chosen ICL offload module;
+ * iscsid(8) must obey those when negotiating operational parameters.
+ */
+struct iscsi_session_limits {
+       size_t          isl_max_data_segment_length;
 };
 
 /*
@@ -81,20 +91,21 @@ struct iscsi_session_state {
        int             iss_immediate_data;
        int             iss_connected;
        char            iss_reason[ISCSI_REASON_LEN];
-       int             iss_spare[4];
+       char            iss_offload[ISCSI_OFFLOAD_LEN];
+       int             iss_spare[2];
 };
 
 /*
- * For use with iscsid(8).
+ * The following ioctls are used by iscsid(8).
  */
-
 struct iscsi_daemon_request {
        unsigned int                    idr_session_id;
        struct iscsi_session_conf       idr_conf;
        uint8_t                         idr_isid[6];
        uint16_t                        idr_tsih;
        uint16_t                        idr_spare_cid;
-       int                             idr_spare[4];
+       struct iscsi_session_limits     idr_limits;
+       int                             idr_spare[2];
 };
 
 struct iscsi_daemon_handoff {
@@ -182,9 +193,8 @@ struct iscsi_daemon_receive {
 #endif /* ICL_KERNEL_PROXY */
 
 /*
- * For use with iscsictl(8).
+ * The following ioctls are used by iscsictl(8).
  */
-
 struct iscsi_session_add {
        struct iscsi_session_conf       isa_conf;
        int                             isa_spare[4];

Modified: head/usr.bin/iscsictl/iscsi.conf.5
==============================================================================
--- head/usr.bin/iscsictl/iscsi.conf.5  Thu Feb  5 03:56:49 2015        
(r278231)
+++ head/usr.bin/iscsictl/iscsi.conf.5  Thu Feb  5 06:37:59 2015        
(r278232)
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd December 17, 2013
+.Dd February 4, 2015
 .Dt ISCSI.CONF 5
 .Os
 .Sh NAME
@@ -110,6 +110,8 @@ flag of
 The following are not specified in the
 .Sy RFC 3720
 .Bl -tag -width sockbufsize
+.It Cm offload
+Name of selected iSCSI hardware offload driver.
 .It Cm port
 The iSCSI port used by the iSCSI protocol, defaults to 3260.
 .It Cm tags

Modified: head/usr.bin/iscsictl/iscsictl.c
==============================================================================
--- head/usr.bin/iscsictl/iscsictl.c    Thu Feb  5 03:56:49 2015        
(r278231)
+++ head/usr.bin/iscsictl/iscsictl.c    Thu Feb  5 06:37:59 2015        
(r278232)
@@ -327,6 +327,9 @@ conf_from_target(struct iscsi_session_co
                conf->isc_discovery = 1;
        if (targ->t_protocol == PROTOCOL_ISER)
                conf->isc_iser = 1;
+       if (targ->t_offload != NULL)
+               strlcpy(conf->isc_offload, targ->t_offload,
+                   sizeof(conf->isc_offload));
        if (targ->t_header_digest == DIGEST_CRC32C)
                conf->isc_header_digest = ISCSI_DIGEST_CRC32C;
        else
@@ -517,6 +520,7 @@ kernel_list(int iscsi_fd, const struct t
                            state->iss_immediate_data ? "Yes" : "No");
                        printf("iSER (RDMA):      %s\n",
                            conf->isc_iser ? "Yes" : "No");
+                       printf("Offload driver:   %s\n", state->iss_offload);
                        printf("Device nodes:     ");
                        print_periphs(state->iss_id);
                        printf("\n\n");

Modified: head/usr.bin/iscsictl/iscsictl.h
==============================================================================
--- head/usr.bin/iscsictl/iscsictl.h    Thu Feb  5 03:56:49 2015        
(r278231)
+++ head/usr.bin/iscsictl/iscsictl.h    Thu Feb  5 06:37:59 2015        
(r278232)
@@ -72,6 +72,7 @@ struct target {
        int                     t_auth_method;
        int                     t_session_type;
        int                     t_protocol;
+       char                    *t_offload;
        char                    *t_user;
        char                    *t_secret;
        char                    *t_mutual_user;

Modified: head/usr.bin/iscsictl/parse.y
==============================================================================
--- head/usr.bin/iscsictl/parse.y       Thu Feb  5 03:56:49 2015        
(r278231)
+++ head/usr.bin/iscsictl/parse.y       Thu Feb  5 06:37:59 2015        
(r278232)
@@ -57,8 +57,8 @@ extern void   yyrestart(FILE *);
 
 %token AUTH_METHOD HEADER_DIGEST DATA_DIGEST TARGET_NAME TARGET_ADDRESS
 %token INITIATOR_NAME INITIATOR_ADDRESS INITIATOR_ALIAS USER SECRET
-%token MUTUAL_USER MUTUAL_SECRET SEMICOLON SESSION_TYPE PROTOCOL IGNORED
-%token EQUALS OPENING_BRACKET CLOSING_BRACKET
+%token MUTUAL_USER MUTUAL_SECRET SEMICOLON SESSION_TYPE PROTOCOL OFFLOAD
+%token IGNORED EQUALS OPENING_BRACKET CLOSING_BRACKET
 
 %union
 {
@@ -117,6 +117,8 @@ target_entry:
        |
        session_type
        |
+       offload
+       |
        protocol
        |
        ignored
@@ -250,6 +252,14 @@ session_type:      SESSION_TYPE EQUALS STR
        }
        ;
 
+offload:       OFFLOAD EQUALS STR
+       {
+               if (target->t_offload != NULL)
+                       errx(1, "duplicated offload at line %d", lineno);
+               target->t_offload = $3;
+       }
+       ;
+
 protocol:      PROTOCOL EQUALS STR
        {
                if (target->t_protocol != PROTOCOL_UNSPECIFIED)

Modified: head/usr.bin/iscsictl/token.l
==============================================================================
--- head/usr.bin/iscsictl/token.l       Thu Feb  5 03:56:49 2015        
(r278231)
+++ head/usr.bin/iscsictl/token.l       Thu Feb  5 06:37:59 2015        
(r278232)
@@ -63,6 +63,7 @@ tgtChapSecret         { return MUTUAL_SECRET; }
 AuthMethod             { return AUTH_METHOD; }
 SessionType            { return SESSION_TYPE; }
 protocol               { return PROTOCOL; }
+offload                        { return OFFLOAD; }
 port                   { return IGNORED; }
 MaxConnections         { return IGNORED; }
 TargetAlias            { return IGNORED; }

Modified: head/usr.sbin/iscsid/iscsid.c
==============================================================================
--- head/usr.sbin/iscsid/iscsid.c       Thu Feb  5 03:56:49 2015        
(r278231)
+++ head/usr.sbin/iscsid/iscsid.c       Thu Feb  5 06:37:59 2015        
(r278232)
@@ -152,7 +152,8 @@ resolve_addr(const struct connection *co
 
 static struct connection *
 connection_new(unsigned int session_id, const uint8_t isid[8], uint16_t tsih,
-    const struct iscsi_session_conf *conf, int iscsi_fd)
+    const struct iscsi_session_conf *conf, const struct iscsi_session_limits
+    *limits, int iscsi_fd)
 {
        struct connection *conn;
        struct addrinfo *from_ai, *to_ai;
@@ -186,6 +187,7 @@ connection_new(unsigned int session_id, 
         * XXX: Should we sanitize this somehow?
         */
        memcpy(&conn->conn_conf, conf, sizeof(conn->conn_conf));
+       memcpy(&conn->conn_limits, limits, sizeof(conn->conn_limits));
 
        from_addr = conn->conn_conf.isc_initiator_addr;
        to_addr = conn->conn_conf.isc_target_addr;
@@ -443,7 +445,8 @@ handle_request(int iscsi_fd, const struc
        }
 
        conn = connection_new(request->idr_session_id, request->idr_isid,
-           request->idr_tsih, &request->idr_conf, iscsi_fd);
+           request->idr_tsih, &request->idr_conf, &request->idr_limits,
+           iscsi_fd);
        set_timeout(timeout);
        capsicate(conn);
        login(conn);

Modified: head/usr.sbin/iscsid/iscsid.h
==============================================================================
--- head/usr.sbin/iscsid/iscsid.h       Thu Feb  5 03:56:49 2015        
(r278231)
+++ head/usr.sbin/iscsid/iscsid.h       Thu Feb  5 06:37:59 2015        
(r278232)
@@ -51,6 +51,7 @@ struct connection {
        int                     conn_socket;
        unsigned int            conn_session_id;
        struct iscsi_session_conf       conn_conf;
+       struct iscsi_session_limits     conn_limits;
        char                    conn_target_alias[ISCSI_ADDR_LEN];
        uint8_t                 conn_isid[6];
        uint16_t                conn_tsih;

Modified: head/usr.sbin/iscsid/login.c
==============================================================================
--- head/usr.sbin/iscsid/login.c        Thu Feb  5 03:56:49 2015        
(r278231)
+++ head/usr.sbin/iscsid/login.c        Thu Feb  5 06:37:59 2015        
(r278232)
@@ -441,6 +441,10 @@ login_negotiate(struct connection *conn)
        request = login_new_request(conn, BHSLR_STAGE_OPERATIONAL_NEGOTIATION);
        request_keys = keys_new();
 
+       log_debugx("offload \"%s\" limits MaxRecvDataSegmentLength to %zd",
+           conn->conn_conf.isc_offload,
+           conn->conn_limits.isl_max_data_segment_length);
+
        /*
         * The following keys are irrelevant for discovery sessions.
         */
@@ -456,9 +460,9 @@ login_negotiate(struct connection *conn)
 
                keys_add(request_keys, "ImmediateData", "Yes");
                keys_add_int(request_keys, "MaxBurstLength",
-                   2 * ISCSI_MAX_DATA_SEGMENT_LENGTH);
+                   2 * conn->conn_limits.isl_max_data_segment_length);
                keys_add_int(request_keys, "FirstBurstLength",
-                   ISCSI_MAX_DATA_SEGMENT_LENGTH);
+                   conn->conn_limits.isl_max_data_segment_length);
                keys_add(request_keys, "InitialR2T", "Yes");
                keys_add(request_keys, "MaxOutstandingR2T", "1");
        } else {
@@ -467,7 +471,7 @@ login_negotiate(struct connection *conn)
        }
 
        keys_add_int(request_keys, "MaxRecvDataSegmentLength",
-           ISCSI_MAX_DATA_SEGMENT_LENGTH);
+           conn->conn_limits.isl_max_data_segment_length);
        keys_add(request_keys, "DefaultTime2Wait", "0");
        keys_add(request_keys, "DefaultTime2Retain", "0");
        keys_add(request_keys, "ErrorRecoveryLevel", "0");
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to