diff options
author | Stefan Metzmacher <metze@samba.org> | 2020-05-07 11:06:03 +0200 |
---|---|---|
committer | Stefan Metzmacher <metze@samba.org> | 2020-05-07 14:44:40 +0000 |
commit | d39636acea4fda840b23646b021e24559681b0b0 (patch) | |
tree | 64d83dd5342391a3dcf8c7a05d1e6b150e795ab8 /lib | |
parent | 4ccb58160936d13a06c74ed1c28c855564b50f22 (diff) | |
download | samba-d39636acea4fda840b23646b021e24559681b0b0.tar.gz |
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 <metze@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/socket/interfaces.c | 41 |
1 files changed, 41 insertions, 0 deletions
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 @@ -173,6 +173,42 @@ static void query_iface_speed_from_name(const char *name, uint64_t *speed) 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); +} #endif /**************************************************************************** @@ -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)) >= |