From 0662a0fbca42df8703d23458532245ed521adc50 Mon Sep 17 00:00:00 2001 From: Ziye Yang Date: Mon, 11 May 2020 23:36:29 +0800 Subject: [PATCH] posix: Disable zero copy feature if IP is configured on a loopback device. Purpose: To disabled the zero copy support if IP is configured on a loopback device. To address issue: https://github.com/spdk/spdk/issues/1340 Signed-off-by: Ziye Yang Change-Id: Ia337f108851653c60d259328b6fefd4ba1e3d654 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/2372 Community-CI: Mellanox Build Bot Tested-by: SPDK CI Jenkins Reviewed-by: Jim Harris Reviewed-by: Aleksey Marchuk Reviewed-by: Ben Walker --- module/sock/posix/posix.c | 74 ++++++++++++++++++++++++++++++++++----- 1 file changed, 66 insertions(+), 8 deletions(-) diff --git a/module/sock/posix/posix.c b/module/sock/posix/posix.c index 1effaf7ca..fe60ab42c 100644 --- a/module/sock/posix/posix.c +++ b/module/sock/posix/posix.c @@ -300,7 +300,7 @@ spdk_posix_sock_set_sendbuf(struct spdk_sock *_sock, int sz) } static struct spdk_posix_sock * -_spdk_posix_sock_alloc(int fd) +_spdk_posix_sock_alloc(int fd, bool enable_zero_copy) { struct spdk_posix_sock *sock; #ifdef SPDK_ZEROCOPY @@ -317,6 +317,10 @@ _spdk_posix_sock_alloc(int fd) sock->fd = fd; #ifdef SPDK_ZEROCOPY + if (!enable_zero_copy) { + return sock; + } + /* Try to turn on zero copy sends */ flag = 1; rc = setsockopt(sock->fd, SOL_SOCKET, SO_ZEROCOPY, &flag, sizeof(flag)); @@ -328,6 +332,55 @@ _spdk_posix_sock_alloc(int fd) return sock; } +static bool +sock_is_loopback(int fd) +{ + struct ifaddrs *addrs, *tmp; + struct sockaddr_storage sa = {}; + socklen_t salen; + struct ifreq ifr = {}; + char ip_addr[256], ip_addr_tmp[256]; + int rc; + bool is_loopback = false; + + salen = sizeof(sa); + rc = getsockname(fd, (struct sockaddr *)&sa, &salen); + if (rc != 0) { + return is_loopback; + } + + memset(ip_addr, 0, sizeof(ip_addr)); + rc = get_addr_str((struct sockaddr *)&sa, ip_addr, sizeof(ip_addr)); + if (rc != 0) { + return is_loopback; + } + + getifaddrs(&addrs); + for (tmp = addrs; tmp != NULL; tmp = tmp->ifa_next) { + if (tmp->ifa_addr && (tmp->ifa_flags & IFF_UP) && + (tmp->ifa_addr->sa_family == sa.ss_family)) { + memset(ip_addr_tmp, 0, sizeof(ip_addr_tmp)); + rc = get_addr_str(tmp->ifa_addr, ip_addr_tmp, sizeof(ip_addr_tmp)); + if (rc != 0) { + continue; + } + + if (strncmp(ip_addr, ip_addr_tmp, sizeof(ip_addr)) == 0) { + memcpy(ifr.ifr_name, tmp->ifa_name, sizeof(ifr.ifr_name)); + ioctl(fd, SIOCGIFFLAGS, &ifr); + if (ifr.ifr_flags & IFF_LOOPBACK) { + is_loopback = true; + } + goto end; + } + } + } + +end: + freeifaddrs(addrs); + return is_loopback; +} + static struct spdk_sock * spdk_posix_sock_create(const char *ip, int port, enum spdk_posix_sock_create_type type, @@ -341,6 +394,7 @@ spdk_posix_sock_create(const char *ip, int port, int fd, flag; int val = 1; int rc, sz; + bool enable_zero_copy = true; if (ip == NULL) { return NULL; @@ -478,18 +532,21 @@ retry: return NULL; } - sock = _spdk_posix_sock_alloc(fd); + if (type == SPDK_SOCK_CREATE_LISTEN) { + /* Only enable zero copy for non-loopback sockets. */ + enable_zero_copy = !sock_is_loopback(fd); + } else if (type == SPDK_SOCK_CREATE_CONNECT) { + /* Disable zero copy for client sockets until support is added */ + enable_zero_copy = false; + } + + sock = _spdk_posix_sock_alloc(fd, enable_zero_copy); if (sock == NULL) { SPDK_ERRLOG("sock allocation failed\n"); close(fd); return NULL; } - /* Disable zero copy for client sockets until support is added */ - if (type == SPDK_SOCK_CREATE_CONNECT) { - sock->zcopy = false; - } - return &sock->base; } @@ -546,7 +603,8 @@ spdk_posix_sock_accept(struct spdk_sock *_sock) } #endif - new_sock = _spdk_posix_sock_alloc(fd); + /* Inherit the zero copy feature from the listen socket */ + new_sock = _spdk_posix_sock_alloc(fd, sock->zcopy); if (new_sock == NULL) { close(fd); return NULL;