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_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 *);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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];
|
||||||
|
@ -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
|
||||||
|
@ -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");
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
||||||
|
@ -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; }
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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");
|
||||||
|
Loading…
Reference in New Issue
Block a user