sock: Add spdk_sock_readv(sock, iov, iovcnt)

Add an new API spdk_sock_readv(sock, iov, iovcnt) to the sock
library. This will be used in SPDK iSCSI target first.

Implementation was done based on vcom_socket_readv in VPP.

Change-Id: I88a8f2af4856b1035165b78d76b4a4f4587b265d
Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/446343
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
This commit is contained in:
Shuhei Matsumoto 2019-02-27 08:58:24 +09:00 committed by Changpeng Liu
parent e80efe8f61
commit 1ee8deae9c
6 changed files with 114 additions and 2 deletions

View File

@ -126,6 +126,17 @@ ssize_t spdk_sock_recv(struct spdk_sock *sock, void *buf, size_t len);
*/
ssize_t spdk_sock_writev(struct spdk_sock *sock, struct iovec *iov, int iovcnt);
/**
* Read message from the given socket to the I/O vector array.
*
* \param sock Socket to receive message.
* \param iov I/O vector.
* \param iovcnt Number of I/O vectors in the array.
*
* \return the length of the received message on success, -1 on failure.
*/
ssize_t spdk_sock_readv(struct spdk_sock *sock, struct iovec *iov, int iovcnt);
/**
* Set the value used to specify the low water mark (in bytes) for this socket.
*

View File

@ -75,6 +75,7 @@ struct spdk_net_impl {
struct spdk_sock *(*accept)(struct spdk_sock *sock);
int (*close)(struct spdk_sock *sock);
ssize_t (*recv)(struct spdk_sock *sock, void *buf, size_t len);
ssize_t (*readv)(struct spdk_sock *sock, struct iovec *iov, int iovcnt);
ssize_t (*writev)(struct spdk_sock *sock, struct iovec *iov, int iovcnt);
int (*set_recvlowat)(struct spdk_sock *sock, int nbytes);

View File

@ -372,6 +372,14 @@ spdk_posix_sock_recv(struct spdk_sock *_sock, void *buf, size_t len)
return recv(sock->fd, buf, len, MSG_DONTWAIT);
}
static ssize_t
spdk_posix_sock_readv(struct spdk_sock *_sock, struct iovec *iov, int iovcnt)
{
struct spdk_posix_sock *sock = __posix_sock(_sock);
return readv(sock->fd, iov, iovcnt);
}
static ssize_t
spdk_posix_sock_writev(struct spdk_sock *_sock, struct iovec *iov, int iovcnt)
{
@ -588,6 +596,7 @@ static struct spdk_net_impl g_posix_net_impl = {
.accept = spdk_posix_sock_accept,
.close = spdk_posix_sock_close,
.recv = spdk_posix_sock_recv,
.readv = spdk_posix_sock_readv,
.writev = spdk_posix_sock_writev,
.set_recvlowat = spdk_posix_sock_set_recvlowat,
.set_recvbuf = spdk_posix_sock_set_recvbuf,

View File

@ -129,6 +129,17 @@ spdk_sock_recv(struct spdk_sock *sock, void *buf, size_t len)
return sock->net_impl->recv(sock, buf, len);
}
ssize_t
spdk_sock_readv(struct spdk_sock *sock, struct iovec *iov, int iovcnt)
{
if (sock == NULL) {
errno = EBADF;
return -1;
}
return sock->net_impl->readv(sock, iov, iovcnt);
}
ssize_t
spdk_sock_writev(struct spdk_sock *sock, struct iovec *iov, int iovcnt)
{
@ -140,7 +151,6 @@ spdk_sock_writev(struct spdk_sock *sock, struct iovec *iov, int iovcnt)
return sock->net_impl->writev(sock, iov, iovcnt);
}
int
spdk_sock_set_recvlowat(struct spdk_sock *sock, int nbytes)
{

View File

@ -385,6 +385,36 @@ spdk_vpp_sock_recv(struct spdk_sock *_sock, void *buf, size_t len)
return rc;
}
static ssize_t
spdk_vpp_sock_readv(struct spdk_sock *_sock, struct iovec *iov, int iovcnt)
{
struct spdk_vpp_sock *sock = __vpp_sock(_sock);
ssize_t total = 0;
int i, rc;
assert(sock != NULL);
assert(g_vpp_initialized);
for (i = 0; i < iovcnt; ++i) {
rc = vppcom_session_read(sock->fd, iov[i].iov_base, iov[i].iov_len);
if (rc < 0) {
if (total > 0) {
break;
} else {
errno = -rc;
return -1;
}
} else {
total += rc;
if (rc < iov[i].iov_len) {
/* Read less than buffer provided, no point to continue. */
break;
}
}
}
return total;
}
static ssize_t
spdk_vpp_sock_writev(struct spdk_sock *_sock, struct iovec *iov, int iovcnt)
{
@ -411,7 +441,6 @@ spdk_vpp_sock_writev(struct spdk_sock *_sock, struct iovec *iov, int iovcnt)
return total;
}
/*
* TODO: Check if there are similar parameters to configure in VPP
* to three below.
@ -609,6 +638,7 @@ static struct spdk_net_impl g_vpp_net_impl = {
.accept = spdk_vpp_sock_accept,
.close = spdk_vpp_sock_close,
.recv = spdk_vpp_sock_recv,
.readv = spdk_vpp_sock_readv,
.writev = spdk_vpp_sock_writev,
.set_recvlowat = spdk_vpp_sock_set_recvlowat,
.set_recvbuf = spdk_vpp_sock_set_recvbuf,

View File

@ -171,6 +171,31 @@ spdk_ut_sock_recv(struct spdk_sock *_sock, void *buf, size_t len)
return len;
}
static ssize_t
spdk_ut_sock_readv(struct spdk_sock *_sock, struct iovec *iov, int iovcnt)
{
struct spdk_ut_sock *sock = __ut_sock(_sock);
size_t len;
char tmp[256];
/* Test implementation only supports single iov for now. */
CU_ASSERT(iovcnt == 1);
len = spdk_min(iov[0].iov_len, sock->bytes_avail);
if (len == 0) {
errno = EAGAIN;
return -1;
}
memcpy(iov[0].iov_base, sock->buf, len);
memcpy(tmp, &sock->buf[len], sock->bytes_avail - len);
memcpy(sock->buf, tmp, sock->bytes_avail - len);
sock->bytes_avail -= len;
return len;
}
static ssize_t
spdk_ut_sock_writev(struct spdk_sock *_sock, struct iovec *iov, int iovcnt)
{
@ -285,6 +310,7 @@ static struct spdk_net_impl g_ut_net_impl = {
.accept = spdk_ut_sock_accept,
.close = spdk_ut_sock_close,
.recv = spdk_ut_sock_recv,
.readv = spdk_ut_sock_readv,
.writev = spdk_ut_sock_writev,
.set_recvlowat = spdk_ut_sock_set_recvlowat,
.set_recvbuf = spdk_ut_sock_set_recvbuf,
@ -331,6 +357,7 @@ _sock(const char *ip, int port)
server_sock = spdk_sock_accept(listen_sock);
SPDK_CU_ASSERT_FATAL(server_sock != NULL);
/* Test spdk_sock_recv */
iov.iov_base = test_string;
iov.iov_len = 7;
bytes_written = spdk_sock_writev(client_sock, &iov, 1);
@ -348,6 +375,30 @@ _sock(const char *ip, int port)
CU_ASSERT(strncmp(test_string, buffer, 7) == 0);
/* Test spdk_sock_readv */
iov.iov_base = test_string;
iov.iov_len = 7;
bytes_written = spdk_sock_writev(client_sock, &iov, 1);
CU_ASSERT(bytes_written == 7);
usleep(1000);
iov.iov_base = buffer;
iov.iov_len = 2;
bytes_read = spdk_sock_readv(server_sock, &iov, 1);
CU_ASSERT(bytes_read == 2);
usleep(1000);
iov.iov_base = buffer + 2;
iov.iov_len = 5;
bytes_read += spdk_sock_readv(server_sock, &iov, 1);
CU_ASSERT(bytes_read == 7);
usleep(1000);
CU_ASSERT(strncmp(test_string, buffer, 7) == 0);
rc = spdk_sock_close(&client_sock);
CU_ASSERT(client_sock == NULL);
CU_ASSERT(rc == 0);