From d39636acea4fda840b23646b021e24559681b0b0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 7 May 2020 11:06:03 +0200 Subject: [PATCH] lib/socket: autodetect RSS using ETHTOOL_GRXRINGS This is also used as part of 'ethtool -n rdma14' and 'ethtool -x rdma14'. ;#> ethtool -n rdma14 8 RX rings available rxclass: Cannot get RX class rule count: Operation not supported RX classification rule retrieval failed ;#> ethtool -x rdma14 RX flow hash indirection table for rdma14 with 8 RX ring(s): 0: 0 1 2 3 4 5 6 7 8: 0 1 2 3 4 5 6 7 RSS hash key: Operation not supported RSS hash function: toeplitz: on xor: off crc32: off Signed-off-by: Stefan Metzmacher Reviewed-by: Ralph Boehme --- lib/socket/interfaces.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/lib/socket/interfaces.c b/lib/socket/interfaces.c index 497bd945984..3157e0cef12 100644 --- a/lib/socket/interfaces.c +++ b/lib/socket/interfaces.c @@ -170,6 +170,42 @@ static void query_iface_speed_from_name(const char *name, uint64_t *speed) } *speed = ((uint64_t)ethtool_cmd_speed(&ecmd)) * 1000 * 1000; +done: + (void)close(fd); +} + +static void query_iface_rx_queues_from_name(const char *name, + uint64_t *rx_queues) +{ + int ret = 0; + struct ethtool_rxnfc rxcmd; + struct ifreq ifr; + int fd; + + fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); + if (fd == -1) { + DBG_ERR("Failed to open socket."); + return; + } + + if (strlen(name) >= IF_NAMESIZE) { + DBG_ERR("Interface name too long."); + goto done; + } + + ZERO_STRUCT(ifr); + strlcpy(ifr.ifr_name, name, IF_NAMESIZE); + + ifr.ifr_data = (void *)&rxcmd; + ZERO_STRUCT(rxcmd); + rxcmd.cmd = ETHTOOL_GRXRINGS; + ret = ioctl(fd, SIOCETHTOOL, &ifr); + if (ret == -1) { + goto done; + } + + *rx_queues = rxcmd.data; + done: (void)close(fd); } @@ -217,6 +253,7 @@ static int _get_interfaces(TALLOC_CTX *mem_ctx, struct iface_struct **pifaces) /* Loop through interfaces, looking for given IP address */ for (ifptr = iflist; ifptr != NULL; ifptr = ifptr->ifa_next) { uint64_t if_speed = 1000 * 1000 * 1000; /* 1Gbps */ + uint64_t rx_queues = 1; if (!ifptr->ifa_addr || !ifptr->ifa_netmask) { continue; @@ -278,9 +315,13 @@ static int _get_interfaces(TALLOC_CTX *mem_ctx, struct iface_struct **pifaces) #ifdef HAVE_ETHTOOL query_iface_speed_from_name(ifptr->ifa_name, &if_speed); + query_iface_rx_queues_from_name(ifptr->ifa_name, &rx_queues); #endif ifaces[total].linkspeed = if_speed; ifaces[total].capability = FSCTL_NET_IFACE_NONE_CAPABLE; + if (rx_queues > 1) { + ifaces[total].capability |= FSCTL_NET_IFACE_RSS_CAPABLE; + } if (strlcpy(ifaces[total].name, ifptr->ifa_name, sizeof(ifaces[total].name)) >= -- 2.34.1