mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-22 21:21:28 +00:00
[PATCH 7/9] iscsid: Implement iser support
Add iser character device handling for accepting and handling connections received through RDMA transport. Add isert_listener device to the poll() loop and handle incoming connection requests. Differentiate between iser and non iser connections Validate RDMAExtension field and reject it if found in iscsi login request. Also, disable immediate data and first burst for iSER since it is not supported yet Signed-off-by: Yan Burman <yanb@mellanox.com> git-svn-id: http://svn.code.sf.net/p/scst/svn/branches/iser@5235 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -62,6 +62,13 @@ enum {
|
||||
key_ifmarker,
|
||||
key_ofmarkint,
|
||||
key_ifmarkint,
|
||||
key_rdma_extensions,
|
||||
key_target_recv_data_length,
|
||||
key_initiator_recv_data_length,
|
||||
key_max_ahs_length,
|
||||
key_tagged_buffer_for_solicited_data_only,
|
||||
key_iser_hello_required,
|
||||
key_max_outstanding_unexpected_pdus,
|
||||
session_key_last,
|
||||
};
|
||||
|
||||
|
||||
@@ -59,6 +59,9 @@ struct iscsi_sess_params {
|
||||
int ifmarker;
|
||||
int ofmarkint;
|
||||
int ifmarkint;
|
||||
int rdma_extensions;
|
||||
int target_recv_data_length;
|
||||
int initiator_recv_data_length;
|
||||
};
|
||||
|
||||
struct iscsi_tgt_params {
|
||||
|
||||
@@ -99,12 +99,13 @@ static void log_params(struct iscsi_sess_params *params)
|
||||
iscsi_get_bool_value(params->data_sequence_inorder),
|
||||
params->error_recovery_level);
|
||||
PRINT_INFO(" HeaderDigest %s, DataDigest %s, OFMarker %s, "
|
||||
"IFMarker %s, OFMarkInt %d, IFMarkInt %d",
|
||||
"IFMarker %s, OFMarkInt %d, IFMarkInt %d, RDMAExtensions %s",
|
||||
iscsi_get_digest_name(params->header_digest, hdigest_name),
|
||||
iscsi_get_digest_name(params->data_digest, ddigest_name),
|
||||
iscsi_get_bool_value(params->ofmarker),
|
||||
iscsi_get_bool_value(params->ifmarker),
|
||||
params->ofmarkint, params->ifmarkint);
|
||||
params->ofmarkint, params->ifmarkint,
|
||||
iscsi_get_bool_value(params->rdma_extensions));
|
||||
}
|
||||
|
||||
/* target_mutex supposed to be locked */
|
||||
@@ -136,6 +137,11 @@ static void sess_params_check(struct iscsi_kern_params_info *info)
|
||||
CHECK_PARAM(info, iparams, ofmarker, 0, 0);
|
||||
CHECK_PARAM(info, iparams, ifmarker, 0, 0);
|
||||
|
||||
/* iSER related parameters */
|
||||
CHECK_PARAM(info, iparams, rdma_extensions, 0, 1);
|
||||
CHECK_PARAM(info, iparams, target_recv_data_length, 512, max_len);
|
||||
CHECK_PARAM(info, iparams, initiator_recv_data_length, 512, max_len);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -164,6 +170,11 @@ static void sess_params_set(struct iscsi_sess_params *params,
|
||||
SET_PARAM(params, info, iparams, ifmarker);
|
||||
SET_PARAM(params, info, iparams, ofmarkint);
|
||||
SET_PARAM(params, info, iparams, ifmarkint);
|
||||
|
||||
/* iSER related parameters */
|
||||
SET_PARAM(params, info, iparams, rdma_extensions);
|
||||
SET_PARAM(params, info, iparams, target_recv_data_length);
|
||||
SET_PARAM(params, info, iparams, initiator_recv_data_length);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -191,6 +202,11 @@ static void sess_params_get(struct iscsi_sess_params *params,
|
||||
GET_PARAM(params, info, iparams, ifmarker);
|
||||
GET_PARAM(params, info, iparams, ofmarkint);
|
||||
GET_PARAM(params, info, iparams, ifmarkint);
|
||||
|
||||
/* iSER related parameters */
|
||||
GET_PARAM(params, info, iparams, rdma_extensions);
|
||||
GET_PARAM(params, info, iparams, target_recv_data_length);
|
||||
GET_PARAM(params, info, iparams, initiator_recv_data_length);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
@@ -199,16 +200,157 @@ static struct connection *alloc_and_init_conn(int fd)
|
||||
pollfd->events = POLLIN;
|
||||
pollfd->revents = 0;
|
||||
|
||||
conn_read_pdu(conn);
|
||||
set_non_blocking(fd);
|
||||
|
||||
out:
|
||||
return conn;
|
||||
}
|
||||
|
||||
static int transmit_iser(int fd, bool start)
|
||||
{
|
||||
int opt = start;
|
||||
return ioctl(fd, RDMA_CORK, &opt, sizeof(opt));
|
||||
}
|
||||
|
||||
static void create_iser_listen_socket(struct pollfd *array)
|
||||
{
|
||||
struct addrinfo hints, *res, *res0;
|
||||
char servname[64];
|
||||
int rc, i;
|
||||
int iser_fd;
|
||||
struct isert_addr_info info;
|
||||
|
||||
iser_fd = create_and_open_dev("isert_scst", 1);
|
||||
|
||||
poll_array[POLL_ISER_LISTEN].fd = iser_fd;
|
||||
if (iser_fd != -1) {
|
||||
poll_array[POLL_ISER_LISTEN].events = POLLIN;
|
||||
|
||||
/* RDMAExtensions */
|
||||
session_keys[key_rdma_extensions].max = 1;
|
||||
session_keys[key_rdma_extensions].local_def = 1;
|
||||
} else {
|
||||
poll_array[POLL_ISER_LISTEN].events = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
memset(servname, 0, sizeof(servname));
|
||||
snprintf(servname, sizeof(servname), "%d", server_port);
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
|
||||
rc = getaddrinfo(server_address, servname, &hints, &res0);
|
||||
if (rc != 0) {
|
||||
log_error("Unable to get address info (%s)!",
|
||||
get_error_str(rc));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
i = 0;
|
||||
for (res = res0; res && i < ISERT_MAX_PORTALS; res = res->ai_next) {
|
||||
memcpy(&info.addr, res->ai_addr, res->ai_addrlen);
|
||||
info.addr_len = res->ai_addrlen;
|
||||
|
||||
rc = ioctl(iser_fd, SET_LISTEN_ADDR, &info);
|
||||
if (rc != 0) {
|
||||
log_error("Unable to set address info (%s)!",
|
||||
strerror(rc));
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
freeaddrinfo(res0);
|
||||
}
|
||||
|
||||
static int iser_getsockname(int fd, struct sockaddr *name, socklen_t *namelen)
|
||||
{
|
||||
struct isert_addr_info addr;
|
||||
int ret;
|
||||
|
||||
ret = ioctl(fd, GET_PORTAL_ADDR, &addr, sizeof(addr));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
memcpy(name, &addr.addr, addr.addr_len);
|
||||
*namelen = addr.addr_len;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int iser_is_discovery(int fd)
|
||||
{
|
||||
int val = 1;
|
||||
|
||||
return ioctl(fd, DISCOVERY_SESSION, &val, sizeof(val));
|
||||
}
|
||||
|
||||
static void iser_accept(int fd)
|
||||
{
|
||||
char buff[256];
|
||||
int ret, conn_fd;
|
||||
struct connection *conn;
|
||||
char target_portal[ISCSI_PORTAL_LEN], target_portal_port[NI_MAXSERV];
|
||||
struct isert_addr_info addr;
|
||||
|
||||
ret = read(fd, buff, sizeof(buff));
|
||||
if (ret == -1)
|
||||
return;
|
||||
|
||||
conn_fd = open(buff, O_RDWR);
|
||||
if (conn_fd == -1) {
|
||||
log_error("open(iser_connection) %s failed: %s\n",
|
||||
buff, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
ret = ioctl(conn_fd, GET_PORTAL_ADDR, &addr, sizeof(addr));
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
ret = getnameinfo((struct sockaddr *)&addr, sizeof(addr), target_portal,
|
||||
sizeof(target_portal), target_portal_port,
|
||||
sizeof(target_portal_port),
|
||||
NI_NUMERICHOST | NI_NUMERICSERV);
|
||||
if (ret != 0) {
|
||||
log_error("Target portal getnameinfo() failed: %s!",
|
||||
get_error_str(ret));
|
||||
return;
|
||||
}
|
||||
|
||||
conn = alloc_and_init_conn(conn_fd);
|
||||
if (!conn)
|
||||
return;
|
||||
|
||||
conn->target_portal = strdup(target_portal);
|
||||
if (conn->target_portal == NULL) {
|
||||
log_error("Unable to duplicate target portal %s", target_portal);
|
||||
conn_free(conn);
|
||||
return;
|
||||
}
|
||||
|
||||
conn->transmit = transmit_iser;
|
||||
conn->getsockname = iser_getsockname;
|
||||
conn->is_discovery = iser_is_discovery;
|
||||
conn->is_iser = true;
|
||||
incoming_cnt++;
|
||||
|
||||
log_info("iSER connect\n");
|
||||
}
|
||||
|
||||
static int transmit_sock(int fd, bool start)
|
||||
{
|
||||
int opt = start;
|
||||
return setsockopt(fd, SOL_TCP, TCP_CORK, &opt, sizeof(opt));
|
||||
}
|
||||
|
||||
static int tcp_is_discovery(int fd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void accept_connection(int listen)
|
||||
{
|
||||
union {
|
||||
@@ -288,6 +430,8 @@ static void accept_connection(int listen)
|
||||
}
|
||||
|
||||
conn->transmit = transmit_sock;
|
||||
conn->getsockname = getsockname;
|
||||
conn->is_discovery = tcp_is_discovery;
|
||||
conn_read_pdu(conn);
|
||||
|
||||
set_non_blocking(fd);
|
||||
@@ -469,6 +613,7 @@ static void event_loop(void)
|
||||
int res, i;
|
||||
|
||||
create_listen_socket(poll_array + POLL_LISTEN);
|
||||
create_iser_listen_socket(poll_array);
|
||||
|
||||
poll_array[POLL_IPC].fd = ipc_fd;
|
||||
poll_array[POLL_IPC].events = POLLIN;
|
||||
@@ -542,6 +687,9 @@ static void event_loop(void)
|
||||
if (poll_array[POLL_SCN].revents)
|
||||
isns_scn_handle(0);
|
||||
|
||||
if (poll_array[POLL_ISER_LISTEN].revents)
|
||||
iser_accept(poll_array[POLL_ISER_LISTEN].fd);
|
||||
|
||||
for (i = 0; i < INCOMING_MAX; i++) {
|
||||
struct connection *conn = incoming[i];
|
||||
struct pollfd *pollfd = &poll_array[POLL_INCOMING + i];
|
||||
|
||||
@@ -42,6 +42,10 @@ static struct iscsi_key login_keys[] = {
|
||||
{"InitiatorAlias",},
|
||||
{"SessionType",},
|
||||
{"TargetName",},
|
||||
{"InitiatorRecvDataSegmentLength",},
|
||||
{"MaxAHSLength",},
|
||||
{"TaggedBufferForSolicitedDataOnly",},
|
||||
{"iSERHelloRequired",},
|
||||
{NULL,},
|
||||
};
|
||||
|
||||
@@ -370,6 +374,26 @@ static void text_scan_login(struct connection *conn)
|
||||
}
|
||||
}
|
||||
|
||||
if (conn->is_iser) {
|
||||
switch (idx) {
|
||||
case key_rdma_extensions:
|
||||
if (val != 1) {
|
||||
login_rsp_ini_err(conn, ISCSI_STATUS_INIT_ERR);
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
case key_initial_r2t:
|
||||
val = 1;
|
||||
break;
|
||||
case key_immediate_data:
|
||||
val = 0;
|
||||
break;
|
||||
}
|
||||
} else if (idx == key_rdma_extensions && val != 0) {
|
||||
login_rsp_ini_err(conn, ISCSI_STATUS_INIT_ERR);
|
||||
goto out;
|
||||
}
|
||||
|
||||
params_check_val(session_keys, idx, &val);
|
||||
params_set_val(session_keys, conn->session_params, idx, &val);
|
||||
|
||||
@@ -503,6 +527,11 @@ static void login_start(struct connection *conn)
|
||||
|
||||
if (session_type) {
|
||||
if (!strcmp(session_type, "Discovery")) {
|
||||
int ret = conn->is_discovery(conn->fd);
|
||||
if (ret) {
|
||||
login_rsp_tgt_err(conn, ISCSI_STATUS_MISSING_FIELDS);
|
||||
return;
|
||||
}
|
||||
conn->session_type = SESSION_DISCOVERY;
|
||||
} else if (strcmp(session_type, "Normal")) {
|
||||
login_rsp_ini_err(conn, ISCSI_STATUS_INV_SESSION_TYPE);
|
||||
|
||||
@@ -28,8 +28,10 @@
|
||||
#include "types.h"
|
||||
#ifdef INSIDE_KERNEL_TREE
|
||||
#include <scst/iscsi_scst.h>
|
||||
#include <scst/isert_scst.h>
|
||||
#else
|
||||
#include "iscsi_scst.h"
|
||||
#include "isert_scst.h"
|
||||
#endif
|
||||
#include "iscsi_hdr.h"
|
||||
#include "param.h"
|
||||
@@ -128,7 +130,11 @@ struct connection {
|
||||
|
||||
struct __qelem clist;
|
||||
|
||||
bool is_iser;
|
||||
|
||||
int (*transmit)(int fd, bool start);
|
||||
int (*getsockname)(int fd, struct sockaddr *name, socklen_t *namelen);
|
||||
int (*is_discovery)(int fd);
|
||||
};
|
||||
|
||||
#define IOSTATE_FREE 0
|
||||
@@ -224,6 +230,7 @@ extern int conn_blocked;
|
||||
enum {
|
||||
POLL_LISTEN,
|
||||
POLL_IPC = POLL_LISTEN + LISTEN_MAX,
|
||||
POLL_ISER_LISTEN,
|
||||
POLL_NL,
|
||||
POLL_ISNS,
|
||||
POLL_SCN_LISTEN,
|
||||
|
||||
@@ -383,5 +383,13 @@ struct iscsi_key session_keys[] = {
|
||||
{"IFMarker", 0, 0, 0, 0, 0, &and_ops},
|
||||
{"OFMarkInt", 2048, 2048, 1, 65535, 0, &marker_ops},
|
||||
{"IFMarkInt", 2048, 2048, 1, 65535, 0, &marker_ops},
|
||||
{"RDMAExtensions", 0, 0, 0, 0, 1, &and_ops},
|
||||
{"TargetRecvDataSegmentLength", 8192, -1, 512, -1, 0, &minimum_ops},
|
||||
{"InitiatorRecvDataSegmentLength", 8192, -1, 512, -1, 0, &minimum_ops},
|
||||
{"MaxAHSLength", 256, 0, 0, -1, 0, &minimum_ops},
|
||||
{"TaggedBufferForSolicitedDataOnly", 0, 0, 0, 0, 0, &and_ops},
|
||||
{"iSERHelloRequired", 0, 0, 0, 0, 0, &and_ops},
|
||||
{"MaxOutstandingUnexpectedPDUs", 0, 0, 0, -1, 0, &minimum_ops},
|
||||
{NULL,},
|
||||
};
|
||||
|
||||
|
||||
@@ -239,10 +239,11 @@ void target_list_build(struct connection *conn, char *target_name)
|
||||
char portal[NI_MAXHOST];
|
||||
int family, i;
|
||||
|
||||
if (getsockname(conn->fd, (struct sockaddr *) &ss1, &slen)) {
|
||||
if (conn->getsockname(conn->fd, (struct sockaddr *) &ss1, &slen)) {
|
||||
log_error("getsockname failed: %m");
|
||||
return;
|
||||
}
|
||||
|
||||
family = ss1.ss_family;
|
||||
|
||||
list_for_each_entry(target, &targets_list, tlist) {
|
||||
|
||||
Reference in New Issue
Block a user