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:
parent
35eeacca92
commit
82babffba9
@ -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 *);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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];
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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; }
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
Loading…
Reference in New Issue
Block a user