Decouple iSCSI connection limits from defaults.

If initiator does not negotiate some parameter, it expects one to get
default value, not some unknown remote hardware limit.  On the side side,
if some parameter is negotiated, its default value from RFC should not
be used for anything.
This commit is contained in:
Alexander Motin 2017-01-14 18:04:12 +00:00
parent 00ea8a5fc9
commit 59c6e3a58f
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=312190
3 changed files with 48 additions and 26 deletions

View File

@ -1582,6 +1582,7 @@ connection_new(struct portal *portal, int fd, const char *host,
* Default values, from RFC 3720, section 12.
*/
conn->conn_max_recv_data_segment_length = 8192;
conn->conn_max_send_data_segment_length = 8192;
conn->conn_max_burst_length = 262144;
conn->conn_first_burst_length = 65536;
conn->conn_immediate_data = true;

View File

@ -48,8 +48,6 @@
#define MAX_LUNS 1024
#define MAX_NAME_LEN 223
#define MAX_DATA_SEGMENT_LENGTH (128 * 1024)
#define MAX_BURST_LENGTH 16776192
#define FIRST_BURST_LENGTH (128 * 1024)
#define SOCKBUF_SIZE 1048576
struct auth {
@ -242,6 +240,10 @@ struct connection {
struct sockaddr_storage conn_initiator_sa;
uint32_t conn_cmdsn;
uint32_t conn_statsn;
int conn_max_recv_data_segment_limit;
int conn_max_send_data_segment_limit;
int conn_max_burst_limit;
int conn_first_burst_limit;
int conn_max_recv_data_segment_length;
int conn_max_send_data_segment_length;
int conn_max_burst_length;

View File

@ -557,13 +557,15 @@ login_negotiate_key(struct pdu *request, const char *name,
* our MaxRecvDataSegmentLength is not influenced by the
* initiator in any way.
*/
if ((int)tmp > conn->conn_max_send_data_segment_length) {
log_debugx("capping max_send_data_segment_length "
if ((int)tmp > conn->conn_max_send_data_segment_limit) {
log_debugx("capping MaxRecvDataSegmentLength "
"from %zd to %d", tmp,
conn->conn_max_send_data_segment_length);
tmp = conn->conn_max_send_data_segment_length;
conn->conn_max_send_data_segment_limit);
tmp = conn->conn_max_send_data_segment_limit;
}
conn->conn_max_send_data_segment_length = tmp;
conn->conn_max_recv_data_segment_length =
conn->conn_max_recv_data_segment_limit;
keys_add_int(response_keys, name,
conn->conn_max_recv_data_segment_length);
} else if (strcmp(name, "MaxBurstLength") == 0) {
@ -572,10 +574,10 @@ login_negotiate_key(struct pdu *request, const char *name,
login_send_error(request, 0x02, 0x00);
log_errx(1, "received invalid MaxBurstLength");
}
if ((int)tmp > conn->conn_max_burst_length) {
if ((int)tmp > conn->conn_max_burst_limit) {
log_debugx("capping MaxBurstLength from %zd to %d",
tmp, conn->conn_max_burst_length);
tmp = conn->conn_max_burst_length;
tmp, conn->conn_max_burst_limit);
tmp = conn->conn_max_burst_limit;
}
conn->conn_max_burst_length = tmp;
keys_add_int(response_keys, name, tmp);
@ -585,10 +587,10 @@ login_negotiate_key(struct pdu *request, const char *name,
login_send_error(request, 0x02, 0x00);
log_errx(1, "received invalid FirstBurstLength");
}
if ((int)tmp > conn->conn_first_burst_length) {
if ((int)tmp > conn->conn_first_burst_limit) {
log_debugx("capping FirstBurstLength from %zd to %d",
tmp, conn->conn_first_burst_length);
tmp = conn->conn_first_burst_length;
tmp, conn->conn_first_burst_limit);
tmp = conn->conn_first_burst_limit;
}
conn->conn_first_burst_length = tmp;
keys_add_int(response_keys, name, tmp);
@ -694,25 +696,42 @@ login_negotiate(struct connection *conn, struct pdu *request)
* offload, it depends on hardware capabilities.
*/
assert(conn->conn_target != NULL);
conn->conn_max_recv_data_segment_limit = (1 << 24) - 1;
conn->conn_max_send_data_segment_limit = (1 << 24) - 1;
conn->conn_max_burst_limit = (1 << 24) - 1;
conn->conn_first_burst_limit = (1 << 24) - 1;
kernel_limits(conn->conn_portal->p_portal_group->pg_offload,
&conn->conn_max_recv_data_segment_length,
&conn->conn_max_send_data_segment_length,
&conn->conn_max_burst_length,
&conn->conn_first_burst_length);
&conn->conn_max_recv_data_segment_limit,
&conn->conn_max_send_data_segment_limit,
&conn->conn_max_burst_limit,
&conn->conn_first_burst_limit);
/* We expect legal, usable values at this point. */
assert(conn->conn_max_recv_data_segment_length >= 512);
assert(conn->conn_max_recv_data_segment_length < (1 << 24));
assert(conn->conn_max_burst_length >= 512);
assert(conn->conn_max_burst_length < (1 << 24));
assert(conn->conn_first_burst_length >= 512);
assert(conn->conn_first_burst_length < (1 << 24));
assert(conn->conn_first_burst_length <=
conn->conn_max_burst_length);
assert(conn->conn_max_recv_data_segment_limit >= 512);
assert(conn->conn_max_recv_data_segment_limit < (1 << 24));
assert(conn->conn_max_send_data_segment_limit >= 512);
assert(conn->conn_max_send_data_segment_limit < (1 << 24));
assert(conn->conn_max_burst_limit >= 512);
assert(conn->conn_max_burst_limit < (1 << 24));
assert(conn->conn_first_burst_limit >= 512);
assert(conn->conn_first_burst_limit < (1 << 24));
assert(conn->conn_first_burst_limit <=
conn->conn_max_burst_limit);
/*
* Limit default send length in case it won't be negotiated.
* We can't do it for other limits, since they may affect both
* sender and receiver operation, and we must obey defaults.
*/
if (conn->conn_max_send_data_segment_limit <
conn->conn_max_send_data_segment_length) {
conn->conn_max_send_data_segment_limit =
conn->conn_max_send_data_segment_length;
}
} else {
conn->conn_max_recv_data_segment_length =
conn->conn_max_recv_data_segment_limit =
MAX_DATA_SEGMENT_LENGTH;
conn->conn_max_send_data_segment_length =
conn->conn_max_send_data_segment_limit =
MAX_DATA_SEGMENT_LENGTH;
}