diff mbox series

[CLOUD-DEV,v3,3/9] linux-gen: pktio: socket: move common code away from socket pktios

Message ID 1507636815-18816-4-git-send-email-odpbot@yandex.ru
State Superseded
Headers show
Series [CLOUD-DEV,v3,1/9] linux-gen: pktio: introduce generic pktio_ops data storage | expand

Commit Message

Github ODP bot Oct. 10, 2017, noon UTC
From: Bogdan Pricope <bogdan.pricope@linaro.org>


Signed-off-by: Bogdan Pricope <bogdan.pricope@linaro.org>

---
/** Email created from pull request 196 (bogdanPricope:cloud_dev_pktio_ops_data_pr)
 ** https://github.com/Linaro/odp/pull/196
 ** Patch: https://github.com/Linaro/odp/pull/196.patch
 ** Base sha: 3d3c8f71f39ff139695d6f4b8e5ea17502c5f7cf
 ** Merge commit sha: 2bae88983ff377d83fcf9c99bf5c380275454327
 **/
 platform/linux-generic/Makefile.am                 |   2 +
 .../linux-generic/include/odp_pktio_ops_socket.h   |  76 -----
 platform/linux-generic/pktio/common.c              | 367 +++++++++++++++++++++
 platform/linux-generic/pktio/common.h              |  81 +++++
 platform/linux-generic/pktio/dpdk.c                |   1 +
 platform/linux-generic/pktio/ethtool.c             |   1 +
 platform/linux-generic/pktio/ethtool.h             |  15 +
 platform/linux-generic/pktio/netmap.c              |   2 +
 platform/linux-generic/pktio/socket.c              | 354 +-------------------
 platform/linux-generic/pktio/socket_mmap.c         |   2 +
 platform/linux-generic/pktio/tap.c                 |   1 +
 11 files changed, 474 insertions(+), 428 deletions(-)
 create mode 100644 platform/linux-generic/pktio/common.h
 create mode 100644 platform/linux-generic/pktio/ethtool.h
diff mbox series

Patch

diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am
index 539342dfb..6a1e0256d 100644
--- a/platform/linux-generic/Makefile.am
+++ b/platform/linux-generic/Makefile.am
@@ -186,6 +186,8 @@  noinst_HEADERS = \
 		  ${srcdir}/include/odp_packet_internal.h \
 		  ${srcdir}/include/odp_packet_io_internal.h \
 		  ${srcdir}/include/odp_packet_io_ring_internal.h \
+		  ${srcdir}/pktio/ethtool.h \
+		  ${srcdir}/pktio/common.h \
 		  ${srcdir}/pktio/dpdk.h \
 		  ${srcdir}/include/odp_pktio_ops_ipc.h \
 		  ${srcdir}/include/odp_pktio_ops_loopback.h \
diff --git a/platform/linux-generic/include/odp_pktio_ops_socket.h b/platform/linux-generic/include/odp_pktio_ops_socket.h
index 32c49c08e..5ed444df7 100644
--- a/platform/linux-generic/include/odp_pktio_ops_socket.h
+++ b/platform/linux-generic/include/odp_pktio_ops_socket.h
@@ -93,80 +93,4 @@  ethaddrs_equal(unsigned char mac_a[], unsigned char mac_b[])
 	return !memcmp(mac_a, mac_b, ETH_ALEN);
 }
 
-/**
- * Read the MAC address from a packet socket
- */
-int mac_addr_get_fd(int fd, const char *name, unsigned char mac_dst[]);
-
-/**
- * Read the MTU from a packet socket
- */
-uint32_t mtu_get_fd(int fd, const char *name);
-
-/**
- * Enable/Disable promisc mode for a packet socket
- */
-int promisc_mode_set_fd(int fd, const char *name, int enable);
-
-/**
- * Return promisc mode of a packet socket
- */
-int promisc_mode_get_fd(int fd, const char *name);
-
-/**
- * Return link status of a packet socket (up/down)
- */
-int link_status_fd(int fd, const char *name);
-
-/**
- * Get enabled RSS hash protocols of a packet socket
- *
- * @param fd              Socket file descriptor
- * @param name            Interface name
- * @param hash_proto[out] Hash protocols
- *
- * @returns Number enabled hash protocols
- */
-int rss_conf_get_fd(int fd, const char *name,
-		    odp_pktin_hash_proto_t *hash_proto);
-
-/**
- * Get supported RSS hash protocols of a packet socket
- *
- * Can be both read and modified.
- *
- * @param fd              Socket file descriptor
- * @param name            Interface name
- * @param hash_proto[out] Hash protocols
- *
- * @returns Number of supported hash protocols
- */
-int rss_conf_get_supported_fd(int fd, const char *name,
-			      odp_pktin_hash_proto_t *hash_proto);
-
-/**
- * Set RSS hash protocols of a packet socket
- *
- * @param fd              Socket file descriptor
- * @param name            Interface name
- * @param hash_proto      Hash protocols
- *
- * @retval 0 on success
- * @retval <0 on failure
- */
-int rss_conf_set_fd(int fd, const char *name,
-		    const odp_pktin_hash_proto_t *proto);
-
-/**
- * Print enabled RSS hash protocols
- *
- * @param hash_proto      Hash protocols
- */
-void rss_conf_print(const odp_pktin_hash_proto_t *hash_proto);
-
-/**
- * Get ethtool statistics of a packet socket
- */
-int ethtool_stats_get_fd(int fd, const char *name, odp_pktio_stats_t *stats);
-
 #endif
diff --git a/platform/linux-generic/pktio/common.c b/platform/linux-generic/pktio/common.c
index 94add0615..4c952e467 100644
--- a/platform/linux-generic/pktio/common.c
+++ b/platform/linux-generic/pktio/common.c
@@ -9,7 +9,17 @@ 
 
 #include <odp_packet_io_internal.h>
 #include <odp_classification_internal.h>
+#include <pktio/ethtool.h>
+#include <pktio/common.h>
 #include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <linux/ethtool.h>
+#include <linux/sockios.h>
+#include <linux/if_packet.h>
+#include <linux/if_ether.h>
 
 int sock_stats_reset_fd(pktio_entry_t *pktio_entry, int fd)
 {
@@ -82,3 +92,360 @@  int sock_stats_fd(pktio_entry_t *pktio_entry,
 
 	return ret;
 }
+
+/*
+ * ODP_PACKET_SOCKET_MMSG:
+ * ODP_PACKET_SOCKET_MMAP:
+ * ODP_PACKET_NETMAP:
+ */
+uint32_t mtu_get_fd(int fd, const char *name)
+{
+	struct ifreq ifr;
+	int ret;
+
+	snprintf(ifr.ifr_name, IF_NAMESIZE, "%s", name);
+	ret = ioctl(fd, SIOCGIFMTU, &ifr);
+	if (ret < 0) {
+		__odp_errno = errno;
+		ODP_DBG("ioctl(SIOCGIFMTU): %s: \"%s\".\n", strerror(errno),
+			ifr.ifr_name);
+		return 0;
+	}
+	return ifr.ifr_mtu;
+}
+
+/**
+ * ODP_PACKET_SOCKET_MMSG:
+ * ODP_PACKET_SOCKET_MMAP:
+ * ODP_PACKET_NETMAP:
+ */
+int mac_addr_get_fd(int fd, const char *name, unsigned char mac_dst[])
+{
+	struct ifreq ethreq;
+	int ret;
+
+	memset(&ethreq, 0, sizeof(ethreq));
+	snprintf(ethreq.ifr_name, IF_NAMESIZE, "%s", name);
+	ret = ioctl(fd, SIOCGIFHWADDR, &ethreq);
+	if (ret != 0) {
+		__odp_errno = errno;
+		ODP_ERR("ioctl(SIOCGIFHWADDR): %s: \"%s\".\n", strerror(errno),
+			ethreq.ifr_name);
+		return -1;
+	}
+
+	memcpy(mac_dst, (unsigned char *)ethreq.ifr_ifru.ifru_hwaddr.sa_data,
+	       ETH_ALEN);
+	return 0;
+}
+
+/*
+ * ODP_PACKET_SOCKET_MMSG:
+ * ODP_PACKET_SOCKET_MMAP:
+ * ODP_PACKET_NETMAP:
+ */
+int promisc_mode_set_fd(int fd, const char *name, int enable)
+{
+	struct ifreq ifr;
+	int ret;
+
+	snprintf(ifr.ifr_name, IF_NAMESIZE, "%s", name);
+	ret = ioctl(fd, SIOCGIFFLAGS, &ifr);
+	if (ret < 0) {
+		__odp_errno = errno;
+		ODP_DBG("ioctl(SIOCGIFFLAGS): %s: \"%s\".\n", strerror(errno),
+			ifr.ifr_name);
+		return -1;
+	}
+
+	if (enable)
+		ifr.ifr_flags |= IFF_PROMISC;
+	else
+		ifr.ifr_flags &= ~(IFF_PROMISC);
+
+	ret = ioctl(fd, SIOCSIFFLAGS, &ifr);
+	if (ret < 0) {
+		__odp_errno = errno;
+		ODP_DBG("ioctl(SIOCSIFFLAGS): %s: \"%s\".\n", strerror(errno),
+			ifr.ifr_name);
+		return -1;
+	}
+	return 0;
+}
+
+/*
+ * ODP_PACKET_SOCKET_MMSG:
+ * ODP_PACKET_SOCKET_MMAP:
+ * ODP_PACKET_NETMAP:
+ */
+int promisc_mode_get_fd(int fd, const char *name)
+{
+	struct ifreq ifr;
+	int ret;
+
+	snprintf(ifr.ifr_name, IF_NAMESIZE, "%s", name);
+	ret = ioctl(fd, SIOCGIFFLAGS, &ifr);
+	if (ret < 0) {
+		__odp_errno = errno;
+		ODP_DBG("ioctl(SIOCGIFFLAGS): %s: \"%s\".\n", strerror(errno),
+			ifr.ifr_name);
+		return -1;
+	}
+
+	return !!(ifr.ifr_flags & IFF_PROMISC);
+}
+
+/*
+ * ODP_PACKET_SOCKET_MMSG:
+ * ODP_PACKET_SOCKET_MMAP:
+ * ODP_PACKET_NETMAP:
+ */
+int link_status_fd(int fd, const char *name)
+{
+	struct ifreq ifr;
+	int ret;
+
+	snprintf(ifr.ifr_name, IF_NAMESIZE, "%s", name);
+	ret = ioctl(fd, SIOCGIFFLAGS, &ifr);
+	if (ret < 0) {
+		__odp_errno = errno;
+		ODP_DBG("ioctl(SIOCGIFFLAGS): %s: \"%s\".\n", strerror(errno),
+			ifr.ifr_name);
+		return -1;
+	}
+
+	return !!(ifr.ifr_flags & IFF_RUNNING);
+}
+
+/**
+ * Get enabled hash options of a packet socket
+ *
+ * @param fd              Socket file descriptor
+ * @param name            Interface name
+ * @param flow_type       Packet flow type
+ * @param options[out]    Enabled hash options
+ *
+ * @retval 0 on success
+ * @retval <0 on failure
+ */
+static inline int get_rss_hash_options(int fd, const char *name,
+				       uint32_t flow_type, uint64_t *options)
+{
+	struct ifreq ifr;
+	struct ethtool_rxnfc rsscmd;
+
+	memset(&ifr, 0, sizeof(ifr));
+	memset(&rsscmd, 0, sizeof(rsscmd));
+	*options = 0;
+
+	snprintf(ifr.ifr_name, IF_NAMESIZE, "%s", name);
+
+	rsscmd.cmd = ETHTOOL_GRXFH;
+	rsscmd.flow_type = flow_type;
+
+	ifr.ifr_data = (void *)&rsscmd;
+
+	if (ioctl(fd, SIOCETHTOOL, &ifr) < 0)
+		return -1;
+
+	*options = rsscmd.data;
+	return 0;
+}
+
+int rss_conf_get_fd(int fd, const char *name,
+		    odp_pktin_hash_proto_t *hash_proto)
+{
+	uint64_t options;
+	int rss_enabled = 0;
+
+	memset(hash_proto, 0, sizeof(odp_pktin_hash_proto_t));
+
+	get_rss_hash_options(fd, name, IPV4_FLOW, &options);
+	if ((options & RXH_IP_SRC) && (options & RXH_IP_DST)) {
+		hash_proto->proto.ipv4 = 1;
+		rss_enabled++;
+	}
+	get_rss_hash_options(fd, name, TCP_V4_FLOW, &options);
+	if ((options & RXH_IP_SRC) && (options & RXH_IP_DST) &&
+	    (options & RXH_L4_B_0_1) && (options & RXH_L4_B_2_3)) {
+		hash_proto->proto.ipv4_tcp = 1;
+		rss_enabled++;
+	}
+	get_rss_hash_options(fd, name, UDP_V4_FLOW, &options);
+	if ((options & RXH_IP_SRC) && (options & RXH_IP_DST) &&
+	    (options & RXH_L4_B_0_1) && (options & RXH_L4_B_2_3)) {
+		hash_proto->proto.ipv4_udp = 1;
+		rss_enabled++;
+	}
+	get_rss_hash_options(fd, name, IPV6_FLOW, &options);
+	if ((options & RXH_IP_SRC) && (options & RXH_IP_DST)) {
+		hash_proto->proto.ipv6 = 1;
+		rss_enabled++;
+	}
+	get_rss_hash_options(fd, name, TCP_V6_FLOW, &options);
+	if ((options & RXH_IP_SRC) && (options & RXH_IP_DST) &&
+	    (options & RXH_L4_B_0_1) && (options & RXH_L4_B_2_3)) {
+		hash_proto->proto.ipv6_tcp = 1;
+		rss_enabled++;
+	}
+	get_rss_hash_options(fd, name, UDP_V6_FLOW, &options);
+	if ((options & RXH_IP_SRC) && (options & RXH_IP_DST) &&
+	    (options & RXH_L4_B_0_1) && (options & RXH_L4_B_2_3)) {
+		hash_proto->proto.ipv6_udp = 1;
+		rss_enabled++;
+	}
+	return rss_enabled;
+}
+
+/**
+ * Set hash options of a packet socket
+ *
+ * @param fd              Socket file descriptor
+ * @param name            Interface name
+ * @param flow_type       Packet flow type
+ * @param options         Hash options
+ *
+ * @retval 0 on success
+ * @retval <0 on failure
+ */
+static inline int set_rss_hash(int fd, const char *name,
+			       uint32_t flow_type, uint64_t options)
+{
+	struct ifreq ifr;
+	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 = options;
+
+	ifr.ifr_data = (void *)&rsscmd;
+
+	if (ioctl(fd, SIOCETHTOOL, &ifr) < 0)
+		return -1;
+
+	return 0;
+}
+
+int rss_conf_set_fd(int fd, const char *name,
+		    const odp_pktin_hash_proto_t *hash_proto)
+{
+	uint64_t options;
+	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) {
+		options = 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, options))
+			return -1;
+	}
+	if (hash_proto->proto.ipv4_tcp && !cur_hash.proto.ipv4_tcp) {
+		options = 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, options))
+			return -1;
+	}
+	if (hash_proto->proto.ipv6_udp && !cur_hash.proto.ipv6_udp) {
+		options = 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, options))
+			return -1;
+	}
+	if (hash_proto->proto.ipv6_tcp && !cur_hash.proto.ipv6_tcp) {
+		options = 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, options))
+			return -1;
+	}
+	if (hash_proto->proto.ipv4 && !cur_hash.proto.ipv4) {
+		options = RXH_IP_SRC | RXH_IP_DST;
+		if (set_rss_hash(fd, name, IPV4_FLOW, options))
+			return -1;
+	}
+	if (hash_proto->proto.ipv6 && !cur_hash.proto.ipv6) {
+		options = RXH_IP_SRC | RXH_IP_DST;
+		if (set_rss_hash(fd, name, IPV6_FLOW, options))
+			return -1;
+	}
+	return 0;
+}
+
+int rss_conf_get_supported_fd(int fd, const char *name,
+			      odp_pktin_hash_proto_t *hash_proto)
+{
+	uint64_t options;
+	int rss_supported = 0;
+
+	memset(hash_proto, 0, sizeof(odp_pktin_hash_proto_t));
+
+	if (!get_rss_hash_options(fd, name, IPV4_FLOW, &options)) {
+		if (!set_rss_hash(fd, name, IPV4_FLOW, options)) {
+			hash_proto->proto.ipv4 = 1;
+			rss_supported++;
+		}
+	}
+	if (!get_rss_hash_options(fd, name, TCP_V4_FLOW, &options)) {
+		if (!set_rss_hash(fd, name, TCP_V4_FLOW, options)) {
+			hash_proto->proto.ipv4_tcp = 1;
+			rss_supported++;
+		}
+	}
+	if (!get_rss_hash_options(fd, name, UDP_V4_FLOW, &options)) {
+		if (!set_rss_hash(fd, name, UDP_V4_FLOW, options)) {
+			hash_proto->proto.ipv4_udp = 1;
+			rss_supported++;
+		}
+	}
+	if (!get_rss_hash_options(fd, name, IPV6_FLOW, &options)) {
+		if (!set_rss_hash(fd, name, IPV6_FLOW, options)) {
+			hash_proto->proto.ipv6 = 1;
+			rss_supported++;
+		}
+	}
+	if (!get_rss_hash_options(fd, name, TCP_V6_FLOW, &options)) {
+		if (!set_rss_hash(fd, name, TCP_V6_FLOW, options)) {
+			hash_proto->proto.ipv6_tcp = 1;
+			rss_supported++;
+		}
+	}
+	if (!get_rss_hash_options(fd, name, UDP_V6_FLOW, &options)) {
+		if (!set_rss_hash(fd, name, UDP_V6_FLOW, options)) {
+			hash_proto->proto.ipv6_udp = 1;
+			rss_supported++;
+		}
+	}
+	return rss_supported;
+}
+
+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("%s\n", str);
+}
diff --git a/platform/linux-generic/pktio/common.h b/platform/linux-generic/pktio/common.h
new file mode 100644
index 000000000..2940af143
--- /dev/null
+++ b/platform/linux-generic/pktio/common.h
@@ -0,0 +1,81 @@ 
+/* Copyright (c) 2016, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#ifndef ODP_PKTIO_COMMON_H_
+#define ODP_PKTIO_COMMON_H_
+
+/**
+ * Read the MTU from a packet socket
+ */
+uint32_t mtu_get_fd(int fd, const char *name);
+
+/**
+ * Read the MAC address from a packet socket
+ */
+int mac_addr_get_fd(int fd, const char *name, unsigned char mac_dst[]);
+
+/**
+ * Enable/Disable promisc mode for a packet socket
+ */
+int promisc_mode_set_fd(int fd, const char *name, int enable);
+
+/**
+ * Return promisc mode of a packet socket
+ */
+int promisc_mode_get_fd(int fd, const char *name);
+
+/**
+ * Return link status of a packet socket (up/down)
+ */
+int link_status_fd(int fd, const char *name);
+
+/**
+ * Get enabled RSS hash protocols of a packet socket
+ *
+ * @param fd              Socket file descriptor
+ * @param name            Interface name
+ * @param hash_proto[out] Hash protocols
+ *
+ * @returns Number enabled hash protocols
+ */
+int rss_conf_get_fd(int fd, const char *name,
+		    odp_pktin_hash_proto_t *hash_proto);
+
+/**
+ * Get supported RSS hash protocols of a packet socket
+ *
+ * Can be both read and modified.
+ *
+ * @param fd              Socket file descriptor
+ * @param name            Interface name
+ * @param hash_proto[out] Hash protocols
+ *
+ * @returns Number of supported hash protocols
+ */
+int rss_conf_get_supported_fd(int fd, const char *name,
+			      odp_pktin_hash_proto_t *hash_proto);
+
+/**
+ * Set RSS hash protocols of a packet socket
+ *
+ * @param fd              Socket file descriptor
+ * @param name            Interface name
+ * @param hash_proto      Hash protocols
+ *
+ * @retval 0 on success
+ * @retval <0 on failure
+ */
+int rss_conf_set_fd(int fd, const char *name,
+		    const odp_pktin_hash_proto_t *proto);
+
+/**
+ * Print enabled RSS hash protocols
+ *
+ * @param hash_proto      Hash protocols
+ */
+void rss_conf_print(const odp_pktin_hash_proto_t *hash_proto);
+
+#endif /*ODP_PKTIO_COMMON_H_*/
diff --git a/platform/linux-generic/pktio/dpdk.c b/platform/linux-generic/pktio/dpdk.c
index bbe8ddda4..484af82c5 100644
--- a/platform/linux-generic/pktio/dpdk.c
+++ b/platform/linux-generic/pktio/dpdk.c
@@ -24,6 +24,7 @@ 
 #include <odp_classification_internal.h>
 #include <odp_debug_internal.h>
 
+#include <pktio/common.h>
 #include <pktio/dpdk.h>
 #include <protocols/eth.h>
 
diff --git a/platform/linux-generic/pktio/ethtool.c b/platform/linux-generic/pktio/ethtool.c
index b41ce4440..b71666a32 100644
--- a/platform/linux-generic/pktio/ethtool.c
+++ b/platform/linux-generic/pktio/ethtool.c
@@ -19,6 +19,7 @@ 
 #include <odp_api.h>
 #include <odp_debug_internal.h>
 #include <odp_packet_io_internal.h>
+#include <pktio/ethtool.h>
 
 static struct ethtool_gstrings *get_stringset(int fd, struct ifreq *ifr)
 {
diff --git a/platform/linux-generic/pktio/ethtool.h b/platform/linux-generic/pktio/ethtool.h
new file mode 100644
index 000000000..c5a811238
--- /dev/null
+++ b/platform/linux-generic/pktio/ethtool.h
@@ -0,0 +1,15 @@ 
+/* Copyright (c) 2016, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#ifndef ODP_PKTIO_ETHTOOL_H_
+#define ODP_PKTIO_ETHTOOL_H_
+
+/**
+ * Get ethtool statistics of a packet socket
+ */
+int ethtool_stats_get_fd(int fd, const char *name, odp_pktio_stats_t *stats);
+
+#endif /*ODP_PKTIO_ETHTOOL_H_*/
diff --git a/platform/linux-generic/pktio/netmap.c b/platform/linux-generic/pktio/netmap.c
index e2d4baa54..49d38f7f2 100644
--- a/platform/linux-generic/pktio/netmap.c
+++ b/platform/linux-generic/pktio/netmap.c
@@ -24,6 +24,8 @@ 
 #include <odp_classification_datamodel.h>
 #include <odp_classification_inlines.h>
 #include <odp_classification_internal.h>
+#include <pktio/ethtool.h>
+#include <pktio/common.h>
 
 #include <inttypes.h>
 
diff --git a/platform/linux-generic/pktio/socket.c b/platform/linux-generic/pktio/socket.c
index 55d2e27cd..145f56014 100644
--- a/platform/linux-generic/pktio/socket.c
+++ b/platform/linux-generic/pktio/socket.c
@@ -43,6 +43,8 @@ 
 #include <odp_classification_inlines.h>
 #include <odp_classification_internal.h>
 #include <odp/api/hints.h>
+#include <pktio/common.h>
+#include <pktio/ethtool.h>
 
 #include <protocols/eth.h>
 #include <protocols/ip.h>
@@ -99,358 +101,6 @@  int sendmmsg(int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags)
 #define ETHBUF_ALIGN(buf_ptr) ((uint8_t *)ODP_ALIGN_ROUNDUP_PTR((buf_ptr), \
 				sizeof(uint32_t)) + ETHBUF_OFFSET)
 
-/**
- * ODP_PACKET_SOCKET_MMSG:
- * ODP_PACKET_SOCKET_MMAP:
- * ODP_PACKET_NETMAP:
- */
-int mac_addr_get_fd(int fd, const char *name, unsigned char mac_dst[])
-{
-	struct ifreq ethreq;
-	int ret;
-
-	memset(&ethreq, 0, sizeof(ethreq));
-	snprintf(ethreq.ifr_name, IF_NAMESIZE, "%s", name);
-	ret = ioctl(fd, SIOCGIFHWADDR, &ethreq);
-	if (ret != 0) {
-		__odp_errno = errno;
-		ODP_ERR("ioctl(SIOCGIFHWADDR): %s: \"%s\".\n", strerror(errno),
-			ethreq.ifr_name);
-		return -1;
-	}
-
-	memcpy(mac_dst, (unsigned char *)ethreq.ifr_ifru.ifru_hwaddr.sa_data,
-	       ETH_ALEN);
-	return 0;
-}
-
-/*
- * ODP_PACKET_SOCKET_MMSG:
- * ODP_PACKET_SOCKET_MMAP:
- * ODP_PACKET_NETMAP:
- */
-uint32_t mtu_get_fd(int fd, const char *name)
-{
-	struct ifreq ifr;
-	int ret;
-
-	snprintf(ifr.ifr_name, IF_NAMESIZE, "%s", name);
-	ret = ioctl(fd, SIOCGIFMTU, &ifr);
-	if (ret < 0) {
-		__odp_errno = errno;
-		ODP_DBG("ioctl(SIOCGIFMTU): %s: \"%s\".\n", strerror(errno),
-			ifr.ifr_name);
-		return 0;
-	}
-	return ifr.ifr_mtu;
-}
-
-/*
- * ODP_PACKET_SOCKET_MMSG:
- * ODP_PACKET_SOCKET_MMAP:
- * ODP_PACKET_NETMAP:
- */
-int promisc_mode_set_fd(int fd, const char *name, int enable)
-{
-	struct ifreq ifr;
-	int ret;
-
-	snprintf(ifr.ifr_name, IF_NAMESIZE, "%s", name);
-	ret = ioctl(fd, SIOCGIFFLAGS, &ifr);
-	if (ret < 0) {
-		__odp_errno = errno;
-		ODP_DBG("ioctl(SIOCGIFFLAGS): %s: \"%s\".\n", strerror(errno),
-			ifr.ifr_name);
-		return -1;
-	}
-
-	if (enable)
-		ifr.ifr_flags |= IFF_PROMISC;
-	else
-		ifr.ifr_flags &= ~(IFF_PROMISC);
-
-	ret = ioctl(fd, SIOCSIFFLAGS, &ifr);
-	if (ret < 0) {
-		__odp_errno = errno;
-		ODP_DBG("ioctl(SIOCSIFFLAGS): %s: \"%s\".\n", strerror(errno),
-			ifr.ifr_name);
-		return -1;
-	}
-	return 0;
-}
-
-/*
- * ODP_PACKET_SOCKET_MMSG:
- * ODP_PACKET_SOCKET_MMAP:
- * ODP_PACKET_NETMAP:
- */
-int promisc_mode_get_fd(int fd, const char *name)
-{
-	struct ifreq ifr;
-	int ret;
-
-	snprintf(ifr.ifr_name, IF_NAMESIZE, "%s", name);
-	ret = ioctl(fd, SIOCGIFFLAGS, &ifr);
-	if (ret < 0) {
-		__odp_errno = errno;
-		ODP_DBG("ioctl(SIOCGIFFLAGS): %s: \"%s\".\n", strerror(errno),
-			ifr.ifr_name);
-		return -1;
-	}
-
-	return !!(ifr.ifr_flags & IFF_PROMISC);
-}
-
-int link_status_fd(int fd, const char *name)
-{
-	struct ifreq ifr;
-	int ret;
-
-	snprintf(ifr.ifr_name, IF_NAMESIZE, "%s", name);
-	ret = ioctl(fd, SIOCGIFFLAGS, &ifr);
-	if (ret < 0) {
-		__odp_errno = errno;
-		ODP_DBG("ioctl(SIOCGIFFLAGS): %s: \"%s\".\n", strerror(errno),
-			ifr.ifr_name);
-		return -1;
-	}
-
-	return !!(ifr.ifr_flags & IFF_RUNNING);
-}
-
-/**
- * Get enabled hash options of a packet socket
- *
- * @param fd              Socket file descriptor
- * @param name            Interface name
- * @param flow_type       Packet flow type
- * @param options[out]    Enabled hash options
- *
- * @retval 0 on success
- * @retval <0 on failure
- */
-static inline int get_rss_hash_options(int fd, const char *name,
-				       uint32_t flow_type, uint64_t *options)
-{
-	struct ifreq ifr;
-	struct ethtool_rxnfc rsscmd;
-
-	memset(&ifr, 0, sizeof(ifr));
-	memset(&rsscmd, 0, sizeof(rsscmd));
-	*options = 0;
-
-	snprintf(ifr.ifr_name, IF_NAMESIZE, "%s", name);
-
-	rsscmd.cmd = ETHTOOL_GRXFH;
-	rsscmd.flow_type = flow_type;
-
-	ifr.ifr_data = (caddr_t)&rsscmd;
-
-	if (ioctl(fd, SIOCETHTOOL, &ifr) < 0)
-		return -1;
-
-	*options = rsscmd.data;
-	return 0;
-}
-
-int rss_conf_get_fd(int fd, const char *name,
-		    odp_pktin_hash_proto_t *hash_proto)
-{
-	uint64_t options;
-	int rss_enabled = 0;
-
-	memset(hash_proto, 0, sizeof(odp_pktin_hash_proto_t));
-
-	get_rss_hash_options(fd, name, IPV4_FLOW, &options);
-	if ((options & RXH_IP_SRC) && (options & RXH_IP_DST)) {
-		hash_proto->proto.ipv4 = 1;
-		rss_enabled++;
-	}
-	get_rss_hash_options(fd, name, TCP_V4_FLOW, &options);
-	if ((options & RXH_IP_SRC) && (options & RXH_IP_DST) &&
-	    (options & RXH_L4_B_0_1) && (options & RXH_L4_B_2_3)) {
-		hash_proto->proto.ipv4_tcp = 1;
-		rss_enabled++;
-	}
-	get_rss_hash_options(fd, name, UDP_V4_FLOW, &options);
-	if ((options & RXH_IP_SRC) && (options & RXH_IP_DST) &&
-	    (options & RXH_L4_B_0_1) && (options & RXH_L4_B_2_3)) {
-		hash_proto->proto.ipv4_udp = 1;
-		rss_enabled++;
-	}
-	get_rss_hash_options(fd, name, IPV6_FLOW, &options);
-	if ((options & RXH_IP_SRC) && (options & RXH_IP_DST)) {
-		hash_proto->proto.ipv6 = 1;
-		rss_enabled++;
-	}
-	get_rss_hash_options(fd, name, TCP_V6_FLOW, &options);
-	if ((options & RXH_IP_SRC) && (options & RXH_IP_DST) &&
-	    (options & RXH_L4_B_0_1) && (options & RXH_L4_B_2_3)) {
-		hash_proto->proto.ipv6_tcp = 1;
-		rss_enabled++;
-	}
-	get_rss_hash_options(fd, name, UDP_V6_FLOW, &options);
-	if ((options & RXH_IP_SRC) && (options & RXH_IP_DST) &&
-	    (options & RXH_L4_B_0_1) && (options & RXH_L4_B_2_3)) {
-		hash_proto->proto.ipv6_udp = 1;
-		rss_enabled++;
-	}
-	return rss_enabled;
-}
-
-/**
- * Set hash options of a packet socket
- *
- * @param fd              Socket file descriptor
- * @param name            Interface name
- * @param flow_type       Packet flow type
- * @param options         Hash options
- *
- * @retval 0 on success
- * @retval <0 on failure
- */
-static inline int set_rss_hash(int fd, const char *name,
-			       uint32_t flow_type, uint64_t options)
-{
-	struct ifreq ifr;
-	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 = options;
-
-	ifr.ifr_data = (caddr_t)&rsscmd;
-
-	if (ioctl(fd, SIOCETHTOOL, &ifr) < 0)
-		return -1;
-
-	return 0;
-}
-
-int rss_conf_set_fd(int fd, const char *name,
-		    const odp_pktin_hash_proto_t *hash_proto)
-{
-	uint64_t options;
-	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) {
-		options = 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, options))
-			return -1;
-	}
-	if (hash_proto->proto.ipv4_tcp && !cur_hash.proto.ipv4_tcp) {
-		options = 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, options))
-			return -1;
-	}
-	if (hash_proto->proto.ipv6_udp && !cur_hash.proto.ipv6_udp) {
-		options = 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, options))
-			return -1;
-	}
-	if (hash_proto->proto.ipv6_tcp && !cur_hash.proto.ipv6_tcp) {
-		options = 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, options))
-			return -1;
-	}
-	if (hash_proto->proto.ipv4 && !cur_hash.proto.ipv4) {
-		options = RXH_IP_SRC | RXH_IP_DST;
-		if (set_rss_hash(fd, name, IPV4_FLOW, options))
-			return -1;
-	}
-	if (hash_proto->proto.ipv6 && !cur_hash.proto.ipv6) {
-		options = RXH_IP_SRC | RXH_IP_DST;
-		if (set_rss_hash(fd, name, IPV6_FLOW, options))
-			return -1;
-	}
-	return 0;
-}
-
-int rss_conf_get_supported_fd(int fd, const char *name,
-			      odp_pktin_hash_proto_t *hash_proto)
-{
-	uint64_t options;
-	int rss_supported = 0;
-
-	memset(hash_proto, 0, sizeof(odp_pktin_hash_proto_t));
-
-	if (!get_rss_hash_options(fd, name, IPV4_FLOW, &options)) {
-		if (!set_rss_hash(fd, name, IPV4_FLOW, options)) {
-			hash_proto->proto.ipv4 = 1;
-			rss_supported++;
-		}
-	}
-	if (!get_rss_hash_options(fd, name, TCP_V4_FLOW, &options)) {
-		if (!set_rss_hash(fd, name, TCP_V4_FLOW, options)) {
-			hash_proto->proto.ipv4_tcp = 1;
-			rss_supported++;
-		}
-	}
-	if (!get_rss_hash_options(fd, name, UDP_V4_FLOW, &options)) {
-		if (!set_rss_hash(fd, name, UDP_V4_FLOW, options)) {
-			hash_proto->proto.ipv4_udp = 1;
-			rss_supported++;
-		}
-	}
-	if (!get_rss_hash_options(fd, name, IPV6_FLOW, &options)) {
-		if (!set_rss_hash(fd, name, IPV6_FLOW, options)) {
-			hash_proto->proto.ipv6 = 1;
-			rss_supported++;
-		}
-	}
-	if (!get_rss_hash_options(fd, name, TCP_V6_FLOW, &options)) {
-		if (!set_rss_hash(fd, name, TCP_V6_FLOW, options)) {
-			hash_proto->proto.ipv6_tcp = 1;
-			rss_supported++;
-		}
-	}
-	if (!get_rss_hash_options(fd, name, UDP_V6_FLOW, &options)) {
-		if (!set_rss_hash(fd, name, UDP_V6_FLOW, options)) {
-			hash_proto->proto.ipv6_udp = 1;
-			rss_supported++;
-		}
-	}
-	return rss_supported;
-}
-
-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("%s\n", str);
-}
-
 /*
  * ODP_PACKET_SOCKET_MMSG:
  */
diff --git a/platform/linux-generic/pktio/socket_mmap.c b/platform/linux-generic/pktio/socket_mmap.c
index 09ad8137e..c413b1a22 100644
--- a/platform/linux-generic/pktio/socket_mmap.c
+++ b/platform/linux-generic/pktio/socket_mmap.c
@@ -32,6 +32,8 @@ 
 #include <odp_classification_inlines.h>
 #include <odp_classification_internal.h>
 #include <odp/api/hints.h>
+#include <pktio/common.h>
+#include <pktio/ethtool.h>
 
 #include <protocols/eth.h>
 #include <protocols/ip.h>
diff --git a/platform/linux-generic/pktio/tap.c b/platform/linux-generic/pktio/tap.c
index 80a13d236..177066ebe 100644
--- a/platform/linux-generic/pktio/tap.c
+++ b/platform/linux-generic/pktio/tap.c
@@ -45,6 +45,7 @@ 
 #include <odp_packet_internal.h>
 #include <odp_packet_io_internal.h>
 #include <odp_classification_internal.h>
+#include <pktio/common.h>
 
 #define BUF_SIZE 65536