Add iSCSI parameters as defined in the iSER specification. Handle special parameter cases for RDMA: - no digests - do not offer iSER parameters unless initiator requests them - do not offer MRDSL (use [IT]RDSL instead) Except do not advertise MaxOutstandingUnexpectedPDUs just yet, as the open-iscsi initiatior does not understand it. Signed-off-by: Pete Wyckoff <pw at osc.edu> --- usr/iscsi/iscsi_if.h | 5 +++++ usr/iscsi/iscsid.c | 21 ++++++++++++++++++++- usr/iscsi/param.c | 38 ++++++++++++++++++++++++++++++++++++++ usr/iscsi/target.c | 4 ++++ 4 files changed, 67 insertions(+), 1 deletions(-) diff --git a/usr/iscsi/iscsi_if.h b/usr/iscsi/iscsi_if.h index 58a76a2..0e9c2eb 100644 --- a/usr/iscsi/iscsi_if.h +++ b/usr/iscsi/iscsi_if.h @@ -215,6 +215,11 @@ enum iscsi_param { ISCSI_PARAM_OFMARKINT, ISCSI_PARAM_IFMARKINT, ISCSI_PARAM_MAXCONNECTIONS, + /* iSCSI Extensions for RDMA (RFC5046) */ + ISCSI_PARAM_RDMA_EXTENSIONS, + ISCSI_PARAM_TARGET_RDSL, + ISCSI_PARAM_INITIATOR_RDSL, + ISCSI_PARAM_MAX_OUTST_PDU, /* must always be last */ ISCSI_PARAM_MAX, }; diff --git a/usr/iscsi/iscsid.c b/usr/iscsi/iscsid.c index defe3a7..df0fec4 100644 --- a/usr/iscsi/iscsid.c +++ b/usr/iscsi/iscsid.c @@ -270,7 +270,7 @@ static void login_security_done(struct iscsi_connection *conn) static void text_scan_login(struct iscsi_connection *conn) { char *key, *value, *data; - int datasize, idx; + int datasize, idx, is_rdma = 0; struct iscsi_login_rsp *rsp = (struct iscsi_login_rsp *)&conn->rsp.bhs; data = conn->req.data; @@ -289,6 +289,9 @@ static void text_scan_login(struct iscsi_connection *conn) if (idx == ISCSI_PARAM_MAX_RECV_DLENGTH) idx = ISCSI_PARAM_MAX_XMIT_DLENGTH; + if (idx == ISCSI_PARAM_RDMA_EXTENSIONS) + is_rdma = 1; + if (param_str_to_val(session_keys, idx, value, &val) < 0) { if (conn->session_param[idx].state == KEY_STATE_START) { @@ -335,6 +338,15 @@ static void text_scan_login(struct iscsi_connection *conn) text_key_add(conn, key, "NotUnderstood"); } + if (is_rdma) { + /* do not try to do digests, not supported in iser */ + conn->session_param[ISCSI_PARAM_HDRDGST_EN].val = DIGEST_NONE; + conn->session_param[ISCSI_PARAM_DATADGST_EN].val = DIGEST_NONE; + } else { + /* do not offer RDMA, initiator must explicitly request */ + conn->session_param[ISCSI_PARAM_RDMA_EXTENSIONS].val = 0; + } + out: return; } @@ -354,6 +366,13 @@ static int text_check_param(struct iscsi_connection *conn) p[i].state = KEY_STATE_DONE; continue; } + if (p[ISCSI_PARAM_RDMA_EXTENSIONS].val == 1) { + if (i == ISCSI_PARAM_MAX_RECV_DLENGTH) + continue; + } else { + if (i >= ISCSI_PARAM_RDMA_EXTENSIONS) + continue; + } memset(buf, 0, sizeof(buf)); param_val_to_str(session_keys, i, p[i].val, buf); diff --git a/usr/iscsi/param.c b/usr/iscsi/param.c index 9eac62c..76236d1 100644 --- a/usr/iscsi/param.c +++ b/usr/iscsi/param.c @@ -118,6 +118,18 @@ static int minimum_check_val(struct iscsi_key *key, unsigned int *val) return 0; } +static int min_or_zero_check_val(struct iscsi_key *key, unsigned int *val) +{ + int err = 0; + + if (*val != 0 && (*val < key->min || key->max < *val)) { + *val = key->min; + err = -EINVAL; + } + + return 0; +} + static int maximum_check_val(struct iscsi_key *key, unsigned int *val) { int err = 0; @@ -140,6 +152,16 @@ static int minimum_set_val(struct param *param, int idx, unsigned int *val) return 0; } +static int min_or_zero_set_val(struct param *param, int idx, unsigned int *val) +{ + if (*val > param[idx].val || *val == 0) + *val = param[idx].val; + else + param[idx].val = *val; + + return 0; +} + static int maximum_set_val(struct param *param, int idx, unsigned int *val) { if (param[idx].val > *val) @@ -265,6 +287,13 @@ static struct iscsi_key_ops minimum_ops = { .set_val = minimum_set_val, }; +static struct iscsi_key_ops min_or_zero_ops = { + .val_to_str = range_val_to_str, + .str_to_val = range_str_to_val, + .check_val = min_or_zero_check_val, + .set_val = min_or_zero_set_val, +}; + static struct iscsi_key_ops maximum_ops = { .val_to_str = range_val_to_str, .str_to_val = range_str_to_val, @@ -345,6 +374,15 @@ struct iscsi_key session_keys[] = { {"IFMarkInt", 2048, 1, 65535, &marker_ops}, [ISCSI_PARAM_MAXCONNECTIONS] = {"MaxConnections", 1, 1, 65535, &minimum_ops}, + /* iSER draft */ + [ISCSI_PARAM_RDMA_EXTENSIONS] = + {"RDMAExtensions", 0, 0, 1, &and_ops}, + [ISCSI_PARAM_TARGET_RDSL] = + {"TargetRecvDataSegmentLength", 8192, 512, 16777215, &minimum_ops}, + [ISCSI_PARAM_INITIATOR_RDSL] = + {"InitiatorRecvDataSegmentLength", 8192, 512, 16777215, &minimum_ops}, + [ISCSI_PARAM_MAX_OUTST_PDU] = + {"MaxOutstandingUnexpectedPDUs", 0, 2, 4294967295U, &min_or_zero_ops}, [ISCSI_PARAM_MAX] = {NULL,}, }; diff --git a/usr/iscsi/target.c b/usr/iscsi/target.c index ab0685f..0471d15 100644 --- a/usr/iscsi/target.c +++ b/usr/iscsi/target.c @@ -283,6 +283,10 @@ int iscsi_target_create(struct target *t) [ISCSI_PARAM_OFMARKINT] = {0, 2048}, [ISCSI_PARAM_IFMARKINT] = {0, 2048}, [ISCSI_PARAM_MAXCONNECTIONS] = {0, 1}, + [ISCSI_PARAM_RDMA_EXTENSIONS] = {0, 1}, + [ISCSI_PARAM_TARGET_RDSL] = {0, 262144}, + [ISCSI_PARAM_INITIATOR_RDSL] = {0, 262144}, + [ISCSI_PARAM_MAX_OUTST_PDU] = {0, 0}, /* not in open-iscsi */ }; target = malloc(sizeof(*target)); -- 1.5.3.4 |