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
This commit is contained in:
Edward Tomasz Napierala 2015-02-05 06:37:59 +00:00
parent 35eeacca92
commit 82babffba9
12 changed files with 71 additions and 16 deletions

View File

@ -113,6 +113,7 @@ struct icl_conn {
bool ic_disconnecting; bool ic_disconnecting;
bool ic_iser; bool ic_iser;
const char *ic_name; const char *ic_name;
const char *ic_offload;
void (*ic_receive)(struct icl_pdu *); void (*ic_receive)(struct icl_pdu *);
void (*ic_error)(struct icl_conn *); void (*ic_error)(struct icl_conn *);

View File

@ -1185,6 +1185,7 @@ icl_soft_new_conn(const char *name, struct mtx *lock)
#endif #endif
ic->ic_max_data_segment_length = ICL_MAX_DATA_SEGMENT_LENGTH; ic->ic_max_data_segment_length = ICL_MAX_DATA_SEGMENT_LENGTH;
ic->ic_name = name; ic->ic_name = name;
ic->ic_offload = "none";
return (ic); return (ic);
} }

View File

@ -1306,6 +1306,16 @@ iscsi_ioctl_daemon_wait(struct iscsi_softc *sc,
request->idr_tsih = 0; /* New or reinstated session. */ request->idr_tsih = 0; /* New or reinstated session. */
memcpy(&request->idr_conf, &is->is_conf, memcpy(&request->idr_conf, &is->is_conf,
sizeof(request->idr_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); sx_sunlock(&sc->sc_lock);
return (0); return (0);
@ -1731,7 +1741,13 @@ iscsi_ioctl_session_add(struct iscsi_softc *sc, struct iscsi_session_add *isa)
return (EBUSY); 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_receive = iscsi_receive_callback;
is->is_conn->ic_error = iscsi_error_callback; is->is_conn->ic_error = iscsi_error_callback;
is->is_conn->ic_prv0 = is; is->is_conn->ic_prv0 = is;
@ -1836,6 +1852,7 @@ iscsi_ioctl_session_list(struct iscsi_softc *sc, struct iscsi_session_list *isl)
iss.iss_id = is->is_id; iss.iss_id = is->is_id;
strlcpy(iss.iss_target_alias, is->is_target_alias, sizeof(iss.iss_target_alias)); 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_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) if (is->is_conn->ic_header_crc32c)
iss.iss_header_digest = ISCSI_DIGEST_CRC32C; iss.iss_header_digest = ISCSI_DIGEST_CRC32C;

View File

@ -43,6 +43,7 @@
#define ISCSI_ADDR_LEN 47 /* INET6_ADDRSTRLEN + '\0' */ #define ISCSI_ADDR_LEN 47 /* INET6_ADDRSTRLEN + '\0' */
#define ISCSI_ALIAS_LEN 256 /* XXX: Where did it come from? */ #define ISCSI_ALIAS_LEN 256 /* XXX: Where did it come from? */
#define ISCSI_SECRET_LEN 17 /* 16 + '\0' */ #define ISCSI_SECRET_LEN 17 /* 16 + '\0' */
#define ISCSI_OFFLOAD_LEN 8
#define ISCSI_REASON_LEN 64 #define ISCSI_REASON_LEN 64
#define ISCSI_DIGEST_NONE 0 #define ISCSI_DIGEST_NONE 0
@ -65,7 +66,16 @@ struct iscsi_session_conf {
int isc_header_digest; int isc_header_digest;
int isc_data_digest; int isc_data_digest;
int isc_iser; 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_immediate_data;
int iss_connected; int iss_connected;
char iss_reason[ISCSI_REASON_LEN]; 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 { struct iscsi_daemon_request {
unsigned int idr_session_id; unsigned int idr_session_id;
struct iscsi_session_conf idr_conf; struct iscsi_session_conf idr_conf;
uint8_t idr_isid[6]; uint8_t idr_isid[6];
uint16_t idr_tsih; uint16_t idr_tsih;
uint16_t idr_spare_cid; uint16_t idr_spare_cid;
int idr_spare[4]; struct iscsi_session_limits idr_limits;
int idr_spare[2];
}; };
struct iscsi_daemon_handoff { struct iscsi_daemon_handoff {
@ -182,9 +193,8 @@ struct iscsi_daemon_receive {
#endif /* ICL_KERNEL_PROXY */ #endif /* ICL_KERNEL_PROXY */
/* /*
* For use with iscsictl(8). * The following ioctls are used by iscsictl(8).
*/ */
struct iscsi_session_add { struct iscsi_session_add {
struct iscsi_session_conf isa_conf; struct iscsi_session_conf isa_conf;
int isa_spare[4]; int isa_spare[4];

View File

@ -24,7 +24,7 @@
.\" .\"
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd December 17, 2013 .Dd February 4, 2015
.Dt ISCSI.CONF 5 .Dt ISCSI.CONF 5
.Os .Os
.Sh NAME .Sh NAME
@ -110,6 +110,8 @@ flag of
The following are not specified in the The following are not specified in the
.Sy RFC 3720 .Sy RFC 3720
.Bl -tag -width sockbufsize .Bl -tag -width sockbufsize
.It Cm offload
Name of selected iSCSI hardware offload driver.
.It Cm port .It Cm port
The iSCSI port used by the iSCSI protocol, defaults to 3260. The iSCSI port used by the iSCSI protocol, defaults to 3260.
.It Cm tags .It Cm tags

View File

@ -327,6 +327,9 @@ conf_from_target(struct iscsi_session_conf *conf,
conf->isc_discovery = 1; conf->isc_discovery = 1;
if (targ->t_protocol == PROTOCOL_ISER) if (targ->t_protocol == PROTOCOL_ISER)
conf->isc_iser = 1; 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) if (targ->t_header_digest == DIGEST_CRC32C)
conf->isc_header_digest = ISCSI_DIGEST_CRC32C; conf->isc_header_digest = ISCSI_DIGEST_CRC32C;
else else
@ -517,6 +520,7 @@ kernel_list(int iscsi_fd, const struct target *targ __unused,
state->iss_immediate_data ? "Yes" : "No"); state->iss_immediate_data ? "Yes" : "No");
printf("iSER (RDMA): %s\n", printf("iSER (RDMA): %s\n",
conf->isc_iser ? "Yes" : "No"); conf->isc_iser ? "Yes" : "No");
printf("Offload driver: %s\n", state->iss_offload);
printf("Device nodes: "); printf("Device nodes: ");
print_periphs(state->iss_id); print_periphs(state->iss_id);
printf("\n\n"); printf("\n\n");

View File

@ -72,6 +72,7 @@ struct target {
int t_auth_method; int t_auth_method;
int t_session_type; int t_session_type;
int t_protocol; int t_protocol;
char *t_offload;
char *t_user; char *t_user;
char *t_secret; char *t_secret;
char *t_mutual_user; char *t_mutual_user;

View File

@ -57,8 +57,8 @@ extern void yyrestart(FILE *);
%token AUTH_METHOD HEADER_DIGEST DATA_DIGEST TARGET_NAME TARGET_ADDRESS %token AUTH_METHOD HEADER_DIGEST DATA_DIGEST TARGET_NAME TARGET_ADDRESS
%token INITIATOR_NAME INITIATOR_ADDRESS INITIATOR_ALIAS USER SECRET %token INITIATOR_NAME INITIATOR_ADDRESS INITIATOR_ALIAS USER SECRET
%token MUTUAL_USER MUTUAL_SECRET SEMICOLON SESSION_TYPE PROTOCOL IGNORED %token MUTUAL_USER MUTUAL_SECRET SEMICOLON SESSION_TYPE PROTOCOL OFFLOAD
%token EQUALS OPENING_BRACKET CLOSING_BRACKET %token IGNORED EQUALS OPENING_BRACKET CLOSING_BRACKET
%union %union
{ {
@ -117,6 +117,8 @@ target_entry:
| |
session_type session_type
| |
offload
|
protocol protocol
| |
ignored 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 protocol: PROTOCOL EQUALS STR
{ {
if (target->t_protocol != PROTOCOL_UNSPECIFIED) if (target->t_protocol != PROTOCOL_UNSPECIFIED)

View File

@ -63,6 +63,7 @@ tgtChapSecret { return MUTUAL_SECRET; }
AuthMethod { return AUTH_METHOD; } AuthMethod { return AUTH_METHOD; }
SessionType { return SESSION_TYPE; } SessionType { return SESSION_TYPE; }
protocol { return PROTOCOL; } protocol { return PROTOCOL; }
offload { return OFFLOAD; }
port { return IGNORED; } port { return IGNORED; }
MaxConnections { return IGNORED; } MaxConnections { return IGNORED; }
TargetAlias { return IGNORED; } TargetAlias { return IGNORED; }

View File

@ -152,7 +152,8 @@ resolve_addr(const struct connection *conn, const char *address,
static struct connection * static struct connection *
connection_new(unsigned int session_id, const uint8_t isid[8], uint16_t tsih, 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 connection *conn;
struct addrinfo *from_ai, *to_ai; struct addrinfo *from_ai, *to_ai;
@ -186,6 +187,7 @@ connection_new(unsigned int session_id, const uint8_t isid[8], uint16_t tsih,
* XXX: Should we sanitize this somehow? * XXX: Should we sanitize this somehow?
*/ */
memcpy(&conn->conn_conf, conf, sizeof(conn->conn_conf)); 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; from_addr = conn->conn_conf.isc_initiator_addr;
to_addr = conn->conn_conf.isc_target_addr; to_addr = conn->conn_conf.isc_target_addr;
@ -443,7 +445,8 @@ handle_request(int iscsi_fd, const struct iscsi_daemon_request *request, int tim
} }
conn = connection_new(request->idr_session_id, request->idr_isid, 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); set_timeout(timeout);
capsicate(conn); capsicate(conn);
login(conn); login(conn);

View File

@ -51,6 +51,7 @@ struct connection {
int conn_socket; int conn_socket;
unsigned int conn_session_id; unsigned int conn_session_id;
struct iscsi_session_conf conn_conf; struct iscsi_session_conf conn_conf;
struct iscsi_session_limits conn_limits;
char conn_target_alias[ISCSI_ADDR_LEN]; char conn_target_alias[ISCSI_ADDR_LEN];
uint8_t conn_isid[6]; uint8_t conn_isid[6];
uint16_t conn_tsih; uint16_t conn_tsih;

View File

@ -441,6 +441,10 @@ login_negotiate(struct connection *conn)
request = login_new_request(conn, BHSLR_STAGE_OPERATIONAL_NEGOTIATION); request = login_new_request(conn, BHSLR_STAGE_OPERATIONAL_NEGOTIATION);
request_keys = keys_new(); 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. * 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(request_keys, "ImmediateData", "Yes");
keys_add_int(request_keys, "MaxBurstLength", 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", 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, "InitialR2T", "Yes");
keys_add(request_keys, "MaxOutstandingR2T", "1"); keys_add(request_keys, "MaxOutstandingR2T", "1");
} else { } else {
@ -467,7 +471,7 @@ login_negotiate(struct connection *conn)
} }
keys_add_int(request_keys, "MaxRecvDataSegmentLength", 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, "DefaultTime2Wait", "0");
keys_add(request_keys, "DefaultTime2Retain", "0"); keys_add(request_keys, "DefaultTime2Retain", "0");
keys_add(request_keys, "ErrorRecoveryLevel", "0"); keys_add(request_keys, "ErrorRecoveryLevel", "0");