Added functions for fetching, configuring, and printing NIC RSS configurations.
Signed-off-by: Matias Elo <matias....@nokia.com> --- platform/linux-generic/include/odp_packet_socket.h | 18 +++ platform/linux-generic/pktio/socket.c | 164 +++++++++++++++++++++ 2 files changed, 182 insertions(+) diff --git a/platform/linux-generic/include/odp_packet_socket.h b/platform/linux-generic/include/odp_packet_socket.h index a5e0eb3..4c78d0d 100644 --- a/platform/linux-generic/include/odp_packet_socket.h +++ b/platform/linux-generic/include/odp_packet_socket.h @@ -18,6 +18,7 @@ #include <odp/debug.h> #include <odp/pool.h> #include <odp/packet.h> +#include <odp/packet_io.h> #include <linux/version.h> @@ -114,4 +115,21 @@ int promisc_mode_set_fd(int fd, const char *name, int enable); */ int promisc_mode_get_fd(int fd, const char *name); +/** + * Return RSS hash protocols of a packet socket + */ +void rss_conf_get_fd(int fd, const char *name, + odp_pktin_hash_proto_t *hash_proto); + +/** + * Set RSS hash protocols of a packet socket + */ +int rss_conf_set_fd(int fd, const char *name, + const odp_pktin_hash_proto_t *proto); + +/** + * Print enabled RSS hash protocols + */ +void rss_conf_print(const odp_pktin_hash_proto_t *hash_proto); + #endif diff --git a/platform/linux-generic/pktio/socket.c b/platform/linux-generic/pktio/socket.c index d9baca3..8e87980 100644 --- a/platform/linux-generic/pktio/socket.c +++ b/platform/linux-generic/pktio/socket.c @@ -31,6 +31,8 @@ #include <sys/ioctl.h> #include <errno.h> #include <sys/syscall.h> +#include <linux/ethtool.h> +#include <linux/sockios.h> #include <odp.h> #include <odp_packet_socket.h> @@ -182,6 +184,168 @@ int promisc_mode_get_fd(int fd, const char *name) return !!(ifr.ifr_flags & IFF_PROMISC); } +static inline uint64_t get_rss_hash(int fd, const char *name, + uint32_t flow_type) +{ + struct ifreq ifr; + int ret; + struct ethtool_rxnfc rsscmd; + + memset(&rsscmd, 0, sizeof(rsscmd)); + + snprintf(ifr.ifr_name, IF_NAMESIZE, "%s", name); + + rsscmd.cmd = ETHTOOL_GRXFH; + rsscmd.flow_type = flow_type; + + ifr.ifr_data = (caddr_t)&rsscmd; + + ret = ioctl(fd, SIOCETHTOOL, &ifr); + + if (ret < 0) { + __odp_errno = errno; + ODP_ERR("get_rss_hash(): %s\n", strerror(errno)); + return 0; + } + return rsscmd.data; +} + +void rss_conf_get_fd(int fd, const char *name, + odp_pktin_hash_proto_t *hash_proto) +{ + uint64_t bitmap; + + memset(hash_proto, 0, sizeof(odp_pktin_hash_proto_t)); + + bitmap = get_rss_hash(fd, name, IPV4_FLOW); + if ((bitmap & RXH_IP_SRC) && (bitmap & RXH_IP_DST)) + hash_proto->proto.ipv4 = 1; + + bitmap = get_rss_hash(fd, name, TCP_V4_FLOW); + if ((bitmap & RXH_IP_SRC) && (bitmap & RXH_IP_DST) && + (bitmap & RXH_L4_B_0_1) && (bitmap & RXH_L4_B_2_3)) + hash_proto->proto.ipv4_tcp = 1; + + bitmap = get_rss_hash(fd, name, UDP_V4_FLOW); + if ((bitmap & RXH_IP_SRC) && (bitmap & RXH_IP_DST) && + (bitmap & RXH_L4_B_0_1) && (bitmap & RXH_L4_B_2_3)) + hash_proto->proto.ipv4_udp = 1; + + bitmap = get_rss_hash(fd, name, IPV6_FLOW); + if ((bitmap & RXH_IP_SRC) && (bitmap & RXH_IP_DST)) + hash_proto->proto.ipv6 = 1; + + bitmap = get_rss_hash(fd, name, TCP_V6_FLOW); + if ((bitmap & RXH_IP_SRC) && (bitmap & RXH_IP_DST) && + (bitmap & RXH_L4_B_0_1) && (bitmap & RXH_L4_B_2_3)) + hash_proto->proto.ipv6_tcp = 1; + + bitmap = get_rss_hash(fd, name, UDP_V6_FLOW); + if ((bitmap & RXH_IP_SRC) && (bitmap & RXH_IP_DST) && + (bitmap & RXH_L4_B_0_1) && (bitmap & RXH_L4_B_2_3)) + hash_proto->proto.ipv6_udp = 1; +} + +static inline int set_rss_hash(int fd, const char *name, + uint32_t flow_type, uint64_t data) +{ + struct ifreq ifr; + int ret; + struct ethtool_rxnfc rsscmd; + + memset(&rsscmd, 0, sizeof(rsscmd)); + + snprintf(ifr.ifr_name, IF_NAMESIZE, "%s", name); + + rsscmd.cmd = ETHTOOL_SRXFH; + rsscmd.flow_type = flow_type; + rsscmd.data = data; + + ifr.ifr_data = (caddr_t)&rsscmd; + + ret = ioctl(fd, SIOCETHTOOL, &ifr); + + if (ret < 0) { + __odp_errno = errno; + ODP_ERR("set_rss_hash(): %s\n", strerror(errno)); + return -1; + } + return 0; +} + +int rss_conf_set_fd(int fd, const char *name, + const odp_pktin_hash_proto_t *hash_proto) +{ + uint64_t data; + odp_pktin_hash_proto_t cur_hash; + + /* Compare to currently set hash protocols */ + rss_conf_get_fd(fd, name, &cur_hash); + + if (hash_proto->proto.ipv4_udp && !cur_hash.proto.ipv4_udp) { + data = RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 | RXH_L4_B_2_3; + if (set_rss_hash(fd, name, UDP_V4_FLOW, data)) + return -1; + } + if (hash_proto->proto.ipv4_tcp && !cur_hash.proto.ipv4_tcp) { + data = RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 | RXH_L4_B_2_3; + if (set_rss_hash(fd, name, TCP_V4_FLOW, data)) + return -1; + } + if (hash_proto->proto.ipv6_udp && !cur_hash.proto.ipv6_udp) { + data = RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 | RXH_L4_B_2_3; + if (set_rss_hash(fd, name, UDP_V6_FLOW, data)) + return -1; + } + if (hash_proto->proto.ipv6_tcp && !cur_hash.proto.ipv6_tcp) { + data = RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 | RXH_L4_B_2_3; + if (set_rss_hash(fd, name, TCP_V6_FLOW, data)) + return -1; + } + if (hash_proto->proto.ipv4 && !cur_hash.proto.ipv4) { + data = RXH_IP_SRC | RXH_IP_DST; + if (set_rss_hash(fd, name, IPV4_FLOW, data)) + return -1; + } + if (hash_proto->proto.ipv6 && !cur_hash.proto.ipv6) { + data = RXH_IP_SRC | RXH_IP_DST; + if (set_rss_hash(fd, name, IPV6_FLOW, data)) + return -1; + } + return 0; +} + +void rss_conf_print(const odp_pktin_hash_proto_t *hash_proto) +{ int max_len = 512; + char str[max_len]; + int len = 0; + int n = max_len - 1; + + len += snprintf(&str[len], n - len, "RSS conf\n"); + + if (hash_proto->proto.ipv4) + len += snprintf(&str[len], n - len, + " IPV4\n"); + if (hash_proto->proto.ipv4_tcp) + len += snprintf(&str[len], n - len, + " IPV4 TCP\n"); + if (hash_proto->proto.ipv4_udp) + len += snprintf(&str[len], n - len, + " IPV4 UDP\n"); + if (hash_proto->proto.ipv6) + len += snprintf(&str[len], n - len, + " IPV6\n"); + if (hash_proto->proto.ipv6_tcp) + len += snprintf(&str[len], n - len, + " IPV6 TCP\n"); + if (hash_proto->proto.ipv6_udp) + len += snprintf(&str[len], n - len, + " IPV6 UDP\n"); + str[len] = '\0'; + + ODP_PRINT("\n%s\n", str); +} + /* * ODP_PACKET_SOCKET_MMSG: */ -- 1.9.1 _______________________________________________ lng-odp mailing list lng-odp@lists.linaro.org https://lists.linaro.org/mailman/listinfo/lng-odp