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_iser;
const char *ic_name;
const char *ic_offload;
void (*ic_receive)(struct icl_pdu *);
void (*ic_error)(struct icl_conn *);

View File

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

View File

@ -1306,6 +1306,16 @@ iscsi_ioctl_daemon_wait(struct iscsi_softc *sc,
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_softc *sc, struct iscsi_session_add *isa)
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_softc *sc, struct iscsi_session_list *isl)
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;

View File

@ -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];

View File

@ -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

View File

@ -327,6 +327,9 @@ conf_from_target(struct iscsi_session_conf *conf,
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 target *targ __unused,
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");

View File

@ -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;

View File

@ -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)

View File

@ -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; }

View File

@ -152,7 +152,8 @@ resolve_addr(const struct connection *conn, const char *address,
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, const uint8_t isid[8], uint16_t tsih,
* 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 struct iscsi_daemon_request *request, int tim
}
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);

View File

@ -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;

View File

@ -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");