diff --git a/platform/linux-dpdk/include/api/odp_packet_io.h b/platform/linux-dpdk/include/api/odp_packet_io.h
index bd6868a..787df7d 100644
--- a/platform/linux-dpdk/include/api/odp_packet_io.h
+++ b/platform/linux-dpdk/include/api/odp_packet_io.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014, Linaro Limited
+/* Copyright (c) 2013, Linaro Limited
  * All rights reserved.
  *
  * SPDX-License-Identifier:     BSD-3-Clause
@@ -19,29 +19,29 @@ extern "C" {
 #endif
 
 #include <odp_std_types.h>
+#include <odp_platform_types.h>
 #include <odp_buffer_pool.h>
 #include <odp_packet.h>
 #include <odp_queue.h>
 
-#include <odp_pktio_types.h>
-
-/** ODP packet IO handle */
-typedef uint32_t odp_pktio_t;
-
-/** Invalid packet IO handle */
-#define ODP_PKTIO_INVALID 0
+/** @defgroup odp_packet_io ODP PACKET IO
+ *  Operations on a packet.
+ *  @{
+ */
 
 /**
  * Open an ODP packet IO instance
  *
  * @param dev    Packet IO device
  * @param pool   Pool to use for packet IO
- * @param params Set of parameters to pass to the arch dependent implementation
  *
  * @return ODP packet IO handle or ODP_PKTIO_INVALID on error
+ *
+ * @note dev name loop is specially pktio reserved name for
+ *	 device used for testing. Usually it's loop back
+ *	 interface.
  */
-odp_pktio_t odp_pktio_open(const char *dev, odp_buffer_pool_t pool,
-			   odp_pktio_params_t *params);
+odp_pktio_t odp_pktio_open(const char *dev, odp_buffer_pool_t pool);
 
 /**
  * Close an ODP packet IO instance
@@ -130,21 +130,77 @@ void odp_pktio_set_input(odp_packet_t pkt, odp_pktio_t id);
 odp_pktio_t odp_pktio_get_input(odp_packet_t pkt);
 
 /**
- * Defines the maximum length of mac address supported by this platform
+ * Configure the MTU for a packet IO interface.
+ *
+ * @param[in] id   ODP packet IO handle.
+ * @param[in] mtu  The value of MTU that the interface will be configured to
+ *		   use.
+ *
+ * @retval  0 on success.
+ * @retval -1 if specified mtu can not be handled.
+ * @retval -1 on any other error or illegal input parameters.
+ */
+int odp_pktio_set_mtu(odp_pktio_t id, int mtu);
+
+/**
+ * Return the currently configured MTU value of a packet IO interface.
+ *
+ * @param[in] id  ODP packet IO handle.
+ *
+ * @retval MTU value >0 on success.
+ * @retval -1 on any error or not existance pktio id.
+ */
+int odp_pktio_mtu(odp_pktio_t id);
+
+/**
+ * Enable/Disable promiscuous mode on a packet IO interface.
+ *
+ * @param[in] id	ODP packet IO handle.
+ * @param[in] enable	1 to enable, 0 to disable.
+ *
+ * @retval 0 on success.
+ * @retval non-zero on any error.
+ */
+int odp_pktio_promisc_mode_set(odp_pktio_t id, odp_bool_t enable);
+
+/**
+ * Determine if promiscuous mode is enabled for a packet IO interface.
+ *
+ * @param[in] id ODP packet IO handle.
+ *
+ * @retval  1 if promiscuous mode is enabled.
+ * @retval  0 if promiscuous mode is disabled.
+ * @retval -1 on any error.
+*/
+int odp_pktio_promisc_mode(odp_pktio_t id);
+
+/**
+ * Get the default MAC address of a packet IO interface.
+ *
+ * @param	id	  ODP packet IO handle.
+ * @param[out]	mac_addr  Storage for MAC address of the packet IO interface.
+ * @param	addr_size Storage size for the address
+ *
+ * @retval Number of bytes written on success, 0 on failure.
  */
-#define ODP_MAC_ADDR_MAX_LENGTH	ETH_ALEN
+size_t odp_pktio_mac_addr(odp_pktio_t id, void *mac_addr,
+			  size_t addr_size);
 
 /**
  * Get mac address of the interface
  *
- * @param id		ODP packet IO handle
- * @param mac_addr	Storage for Mac address of the packet IO interface
- *			Storage provided by the caller should be equal
- *			to ODP_MAC_ADDR_MAX_LENGTH (filled by function)
+ * @param id           ODP packet IO handle
+ * @param mac_addr     Storage for Mac address of the packet IO interface
+ *                     Storage provided by the caller should be equal
+ *                     to ODP_MAC_ADDR_MAX_LENGTH (filled by function)
  * @return  0 on success or -1 on error
-**/
+ */
 int odp_pktio_get_mac_addr(odp_pktio_t id, unsigned char *mac_addr);
 
+/**
+ * @}
+ */
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/platform/linux-dpdk/include/odp_packet_io_internal.h b/platform/linux-dpdk/include/odp_packet_io_internal.h
index 9263349..5ece843 100644
--- a/platform/linux-dpdk/include/odp_packet_io_internal.h
+++ b/platform/linux-dpdk/include/odp_packet_io_internal.h
@@ -20,17 +20,36 @@ extern "C" {
 
 #include <odp_spinlock.h>
 #include <odp_packet_socket.h>
-#ifdef ODP_HAVE_NETMAP
-#include <odp_packet_netmap.h>
-#endif
+#include <odp_classification_datamodel.h>
+#include <odp_align_internal.h>
+
+#include <odp_config.h>
+#include <odp_hints.h>
+#include <linux/if.h>
+
+/* DPDK */
 #include <odp_packet_dpdk.h>
 
+/**
+ * Packet IO types
+ */
+typedef enum {
+	ODP_PKTIO_TYPE_SOCKET_BASIC = 0x1,
+	ODP_PKTIO_TYPE_SOCKET_MMSG,
+	ODP_PKTIO_TYPE_SOCKET_MMAP,
+} odp_pktio_type_t;
+
 struct pktio_entry {
 	odp_spinlock_t lock;		/**< entry spinlock */
 	int taken;			/**< is entry taken(1) or free(0) */
 	odp_queue_t inq_default;	/**< default input queue, if set */
 	odp_queue_t outq_default;	/**< default out queue */
-	odp_pktio_params_t params;	/**< pktio parameters */
+	odp_pktio_type_t type;		/**< pktio type */
+	pkt_sock_t pkt_sock;		/**< using socket API for IO */
+	pkt_sock_mmap_t pkt_sock_mmap;	/**< using socket mmap API for IO */
+	classifier_t cls;		/**< classifier linked with this pktio*/
+	char name[IFNAMSIZ];		/**< name of pktio provided to
+					   pktio_open() */
 	pkt_dpdk_t pkt_dpdk;		/**< using DPDK API for IO */
 };
 
@@ -39,6 +58,21 @@ typedef union {
 	uint8_t pad[ODP_CACHE_LINE_SIZE_ROUNDUP(sizeof(struct pktio_entry))];
 } pktio_entry_t;
 
+typedef struct {
+	pktio_entry_t entries[ODP_CONFIG_PKTIO_ENTRIES];
+} pktio_table_t;
+
+extern void *pktio_entry_ptr[];
+
+
+static inline pktio_entry_t *get_pktio_entry(odp_pktio_t id)
+{
+	if (odp_unlikely(id == ODP_PKTIO_INVALID ||
+			 id > ODP_CONFIG_PKTIO_ENTRIES))
+		return NULL;
+
+	return pktio_entry_ptr[id - 1];
+}
 #ifdef __cplusplus
 }
 #endif
diff --git a/platform/linux-dpdk/odp_packet_io.c b/platform/linux-dpdk/odp_packet_io.c
index 79394bb..b6d1d35 100644
--- a/platform/linux-dpdk/odp_packet_io.c
+++ b/platform/linux-dpdk/odp_packet_io.c
@@ -16,34 +16,21 @@
 #ifdef ODP_HAVE_NETMAP
 #include <odp_packet_netmap.h>
 #endif
-#include <odp_hints.h>
 #include <odp_config.h>
 #include <odp_queue_internal.h>
 #include <odp_schedule_internal.h>
-#include <odp_debug.h>
-
-#include <odp_pktio_socket.h>
-#ifdef ODP_HAVE_NETMAP
-#include <odp_pktio_netmap.h>
-#endif
+#include <odp_classification_internal.h>
+#include <odp_debug_internal.h>
 
 #include <string.h>
-
-typedef struct {
-	pktio_entry_t entries[ODP_CONFIG_PKTIO_ENTRIES];
-} pktio_table_t;
+#include <sys/ioctl.h>
+#include <linux/if_arp.h>
+#include <ifaddrs.h>
 
 static pktio_table_t *pktio_tbl;
 
-
-static pktio_entry_t *get_entry(odp_pktio_t id)
-{
-	if (odp_unlikely(id == ODP_PKTIO_INVALID ||
-			 id > ODP_CONFIG_PKTIO_ENTRIES))
-		return NULL;
-
-	return &pktio_tbl->entries[id - 1];
-}
+/* pktio pointer entries ( for inlines) */
+void *pktio_entry_ptr[ODP_CONFIG_PKTIO_ENTRIES];
 
 int odp_pktio_init_global(void)
 {
@@ -65,10 +52,12 @@ int odp_pktio_init_global(void)
 	memset(pktio_tbl, 0, sizeof(pktio_table_t));
 
 	for (id = 1; id <= ODP_CONFIG_PKTIO_ENTRIES; ++id) {
-		pktio_entry = get_entry(id);
+		pktio_entry = &pktio_tbl->entries[id - 1];
 
 		odp_spinlock_init(&pktio_entry->s.lock);
+		odp_spinlock_init(&pktio_entry->s.cls.lock);
 
+		pktio_entry_ptr[id - 1] = pktio_entry;
 		/* Create a default output queue for each pktio resource */
 		snprintf(name, sizeof(name), "%i-pktio_outq_default", (int)id);
 		name[ODP_QUEUE_NAME_LEN-1] = '\0';
@@ -115,16 +104,27 @@ static void unlock_entry(pktio_entry_t *entry)
 	odp_spinlock_unlock(&entry->s.lock);
 }
 
-static void init_pktio_entry(pktio_entry_t *entry, odp_pktio_params_t *params)
+static void lock_entry_classifier(pktio_entry_t *entry)
+{
+	odp_spinlock_lock(&entry->s.lock);
+	odp_spinlock_lock(&entry->s.cls.lock);
+}
+
+static void unlock_entry_classifier(pktio_entry_t *entry)
+{
+	odp_spinlock_unlock(&entry->s.cls.lock);
+	odp_spinlock_unlock(&entry->s.lock);
+}
+
+static void init_pktio_entry(pktio_entry_t *entry)
 {
 	set_taken(entry);
 	entry->s.inq_default = ODP_QUEUE_INVALID;
 	memset(&entry->s.pkt_dpdk, 0, sizeof(entry->s.pkt_dpdk));
-	/* Save pktio parameters, type is the most useful */
-	memcpy(&entry->s.params, params, sizeof(*params));
+	pktio_classifier_init(entry);
 }
 
-static odp_pktio_t alloc_lock_pktio_entry(odp_pktio_params_t *params)
+static odp_pktio_t alloc_lock_pktio_entry(void)
 {
 	odp_pktio_t id;
 	pktio_entry_t *entry;
@@ -133,13 +133,13 @@ static odp_pktio_t alloc_lock_pktio_entry(odp_pktio_params_t *params)
 	for (i = 0; i < ODP_CONFIG_PKTIO_ENTRIES; ++i) {
 		entry = &pktio_tbl->entries[i];
 		if (is_free(entry)) {
-			lock_entry(entry);
+			lock_entry_classifier(entry);
 			if (is_free(entry)) {
-				init_pktio_entry(entry, params);
+				init_pktio_entry(entry);
 				id = i + 1;
 				return id; /* return with entry locked! */
 			}
-			unlock_entry(entry);
+			unlock_entry_classifier(entry);
 		}
 	}
 
@@ -148,7 +148,7 @@ static odp_pktio_t alloc_lock_pktio_entry(odp_pktio_params_t *params)
 
 static int free_pktio_entry(odp_pktio_t id)
 {
-	pktio_entry_t *entry = get_entry(id);
+	pktio_entry_t *entry = get_pktio_entry(id);
 
 	if (entry == NULL)
 		return -1;
@@ -158,28 +158,22 @@ static int free_pktio_entry(odp_pktio_t id)
 	return 0;
 }
 
-odp_pktio_t odp_pktio_open(const char *dev, odp_buffer_pool_t pool,
-			   odp_pktio_params_t *params)
+odp_pktio_t odp_pktio_open(const char *dev, odp_buffer_pool_t pool)
 {
 	odp_pktio_t id;
 	pktio_entry_t *pktio_entry;
 	int res;
 
-	if (params == NULL) {
-		ODP_ERR("Invalid pktio params\n");
-		return ODP_PKTIO_INVALID;
-	}
-
 	ODP_DBG("Allocating dpdk pktio\n");
 
-	id = alloc_lock_pktio_entry(params);
+	id = alloc_lock_pktio_entry();
 	if (id == ODP_PKTIO_INVALID) {
 		ODP_ERR("No resources available.\n");
 		return ODP_PKTIO_INVALID;
 	}
 	/* if successful, alloc_pktio_entry() returns with the entry locked */
 
-	pktio_entry = get_entry(id);
+	pktio_entry = get_pktio_entry(id);
 
 	res = setup_pkt_dpdk(&pktio_entry->s.pkt_dpdk, dev, pool);
 	if (res == -1) {
@@ -188,7 +182,7 @@ odp_pktio_t odp_pktio_open(const char *dev, odp_buffer_pool_t pool,
 		id = ODP_PKTIO_INVALID;
 	}
 
-	unlock_entry(pktio_entry);
+	unlock_entry_classifier(pktio_entry);
 	return id;
 }
 
@@ -197,7 +191,7 @@ int odp_pktio_close(odp_pktio_t id)
 	pktio_entry_t *entry;
 	int res = -1;
 
-	entry = get_entry(id);
+	entry = get_pktio_entry(id);
 	if (entry == NULL)
 		return -1;
 
@@ -226,7 +220,7 @@ odp_pktio_t odp_pktio_get_input(odp_packet_t pkt)
 
 int odp_pktio_recv(odp_pktio_t id, odp_packet_t pkt_table[], unsigned len)
 {
-	pktio_entry_t *pktio_entry = get_entry(id);
+	pktio_entry_t *pktio_entry = get_pktio_entry(id);
 	int pkts;
 	int i;
 
@@ -249,7 +243,7 @@ int odp_pktio_recv(odp_pktio_t id, odp_packet_t pkt_table[], unsigned len)
 
 int odp_pktio_send(odp_pktio_t id, odp_packet_t pkt_table[], unsigned len)
 {
-	pktio_entry_t *pktio_entry = get_entry(id);
+	pktio_entry_t *pktio_entry = get_pktio_entry(id);
 	int pkts;
 
 	if (pktio_entry == NULL)
@@ -265,15 +259,17 @@ int odp_pktio_send(odp_pktio_t id, odp_packet_t pkt_table[], unsigned len)
 
 int odp_pktio_inq_setdef(odp_pktio_t id, odp_queue_t queue)
 {
-	pktio_entry_t *pktio_entry = get_entry(id);
+	pktio_entry_t *pktio_entry = get_pktio_entry(id);
 	queue_entry_t *qentry = queue_to_qentry(queue);
 
-	if (pktio_entry == NULL || qentry == NULL)
+	if (pktio_entry == NULL || qentry == ODP_QUEUE_INVALID)
 		return -1;
 
 	if (qentry->s.type != ODP_QUEUE_TYPE_PKTIN)
 		return -1;
 
+	qentry = queue_to_qentry(queue);
+
 	lock_entry(pktio_entry);
 	pktio_entry->s.inq_default = queue;
 	unlock_entry(pktio_entry);
@@ -295,7 +291,7 @@ int odp_pktio_inq_remdef(odp_pktio_t id)
 
 odp_queue_t odp_pktio_inq_getdef(odp_pktio_t id)
 {
-	pktio_entry_t *pktio_entry = get_entry(id);
+	pktio_entry_t *pktio_entry = get_pktio_entry(id);
 
 	if (pktio_entry == NULL)
 		return ODP_QUEUE_INVALID;
@@ -305,7 +301,7 @@ odp_queue_t odp_pktio_inq_getdef(odp_pktio_t id)
 
 odp_queue_t odp_pktio_outq_getdef(odp_pktio_t id)
 {
-	pktio_entry_t *pktio_entry = get_entry(id);
+	pktio_entry_t *pktio_entry = get_pktio_entry(id);
 
 	if (pktio_entry == NULL)
 		return ODP_QUEUE_INVALID;
@@ -362,32 +358,32 @@ int pktin_enqueue(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr)
 odp_buffer_hdr_t *pktin_dequeue(queue_entry_t *qentry)
 {
 	odp_buffer_hdr_t *buf_hdr;
+	odp_buffer_t buf;
+	odp_packet_t pkt_tbl[QUEUE_MULTI_MAX];
+	odp_buffer_hdr_t *tmp_hdr_tbl[QUEUE_MULTI_MAX];
+	int pkts, i, j;
 
 	buf_hdr = queue_deq(qentry);
+	if (buf_hdr != NULL)
+		return buf_hdr;
 
-	if (buf_hdr == NULL) {
-		odp_packet_t pkt;
-		odp_buffer_t buf;
-		odp_packet_t pkt_tbl[QUEUE_MULTI_MAX];
-		odp_buffer_hdr_t *tmp_hdr_tbl[QUEUE_MULTI_MAX];
-		int pkts, i, j;
-
-		pkts = odp_pktio_recv(qentry->s.pktin, pkt_tbl,
-				      QUEUE_MULTI_MAX);
-
-		if (pkts > 0) {
-			pkt = pkt_tbl[0];
-			buf = odp_buffer_from_packet(pkt);
-			buf_hdr = odp_buf_to_hdr(buf);
+	pkts = odp_pktio_recv(qentry->s.pktin, pkt_tbl, QUEUE_MULTI_MAX);
+	if (pkts <= 0)
+		return NULL;
 
-			for (i = 1, j = 0; i < pkts; ++i) {
-				buf = odp_buffer_from_packet(pkt_tbl[i]);
-				tmp_hdr_tbl[j++] = odp_buf_to_hdr(buf);
-			}
-			queue_enq_multi(qentry, tmp_hdr_tbl, j);
-		}
+	for (i = 0, j = 0; i < pkts; ++i) {
+		buf = odp_packet_to_buffer(pkt_tbl[i]);
+		buf_hdr = odp_buf_to_hdr(buf);
+		if (0 > packet_classifier(qentry->s.pktin, pkt_tbl[i]))
+			tmp_hdr_tbl[j++] = buf_hdr;
 	}
 
+	if (0 == j)
+		return NULL;
+
+	if (j > 1)
+		queue_enq_multi(qentry, &tmp_hdr_tbl[1], j-1);
+	buf_hdr = tmp_hdr_tbl[0];
 	return buf_hdr;
 }
 
@@ -400,32 +396,179 @@ int pktin_enq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[], int num)
 int pktin_deq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[], int num)
 {
 	int nbr;
+	odp_packet_t pkt_tbl[QUEUE_MULTI_MAX];
+	odp_buffer_hdr_t *tmp_hdr_tbl[QUEUE_MULTI_MAX];
+	odp_buffer_hdr_t *tmp_hdr;
+	odp_buffer_t buf;
+	int pkts, i, j;
 
 	nbr = queue_deq_multi(qentry, buf_hdr, num);
-
-	if (nbr < num) {
-		odp_packet_t pkt_tbl[QUEUE_MULTI_MAX];
-		odp_buffer_hdr_t *tmp_hdr_tbl[QUEUE_MULTI_MAX];
-		odp_buffer_t buf;
-		int pkts, i;
-
-		pkts = odp_pktio_recv(qentry->s.pktin, pkt_tbl,
-				      QUEUE_MULTI_MAX);
-		if (pkts > 0) {
-			for (i = 0; i < pkts; ++i) {
-				buf = odp_buffer_from_packet(pkt_tbl[i]);
-				tmp_hdr_tbl[i] = odp_buf_to_hdr(buf);
-			}
-			queue_enq_multi(qentry, tmp_hdr_tbl, pkts);
-		}
+	if (odp_unlikely(nbr > num))
+		ODP_ABORT("queue_deq_multi req: %d, returned %d\n",
+			  num, nbr);
+
+	/** queue already has number of requsted buffers,
+	 *  do not do receive in that case.
+	 */
+	if (nbr == num)
+		return nbr;
+
+	pkts = odp_pktio_recv(qentry->s.pktin, pkt_tbl, QUEUE_MULTI_MAX);
+	if (pkts <= 0)
+		return nbr;
+
+	for (i = 0, j = 0; i < pkts; ++i) {
+		buf = odp_packet_to_buffer(pkt_tbl[i]);
+		tmp_hdr = odp_buf_to_hdr(buf);
+		if (0 > packet_classifier(qentry->s.pktin, pkt_tbl[i]))
+			tmp_hdr_tbl[j++] = tmp_hdr;
 	}
 
+	if (j)
+		queue_enq_multi(qentry, tmp_hdr_tbl, j);
 	return nbr;
 }
 
+int odp_pktio_set_mtu(odp_pktio_t id, int mtu)
+{
+	pktio_entry_t *entry;
+	int ret;
+
+	if (mtu <= 0) {
+		ODP_DBG("illegal MTU value %d\n", mtu);
+		return -1;
+	}
+
+	entry = get_pktio_entry(id);
+	if (entry == NULL) {
+		ODP_DBG("pktio entry %d does not exist\n", id);
+		return -1;
+	}
+
+	lock_entry(entry);
+
+	if (odp_unlikely(is_free(entry))) {
+		unlock_entry(entry);
+		ODP_DBG("already freed pktio\n");
+		return -1;
+	}
+
+	ret = rte_eth_dev_set_mtu(entry->s.pkt_dpdk.portid, (uint16_t)mtu);
+
+	unlock_entry(entry);
+	return ret;
+}
+
+int odp_pktio_mtu(odp_pktio_t id)
+{
+	pktio_entry_t *entry;
+	int mtu;
+
+	entry = get_pktio_entry(id);
+	if (entry == NULL) {
+		ODP_DBG("pktio entry %d does not exist\n", id);
+		return -1;
+	}
+
+	lock_entry(entry);
+
+	if (odp_unlikely(is_free(entry))) {
+		unlock_entry(entry);
+		ODP_DBG("already freed pktio\n");
+		return -1;
+	}
+
+	rte_eth_dev_get_mtu(entry->s.pkt_dpdk.portid , (uint16_t *)&mtu);
+
+	unlock_entry(entry);
+	return mtu;
+}
+
+int odp_pktio_promisc_mode_set(odp_pktio_t id, odp_bool_t enable)
+{
+	pktio_entry_t *entry;
+
+	entry = get_pktio_entry(id);
+	if (entry == NULL) {
+		ODP_DBG("pktio entry %d does not exist\n", id);
+		return -1;
+	}
+
+	lock_entry(entry);
+
+	if (odp_unlikely(is_free(entry))) {
+		unlock_entry(entry);
+		ODP_DBG("already freed pktio\n");
+		return -1;
+	}
+
+	if (enable)
+		rte_eth_promiscuous_enable(entry->s.pkt_dpdk.portid);
+	else
+		rte_eth_promiscuous_disable(entry->s.pkt_dpdk.portid);
+
+	unlock_entry(entry);
+	return 0;
+}
+
+int odp_pktio_promisc_mode(odp_pktio_t id)
+{
+	pktio_entry_t *entry;
+	int promisc;
+
+	entry = get_pktio_entry(id);
+	if (entry == NULL) {
+		ODP_DBG("pktio entry %d does not exist\n", id);
+		return -1;
+	}
+
+	lock_entry(entry);
+
+	if (odp_unlikely(is_free(entry))) {
+		unlock_entry(entry);
+		ODP_DBG("already freed pktio\n");
+		return -1;
+	}
+
+	promisc = rte_eth_promiscuous_get(entry->s.pkt_dpdk.portid);
+
+	unlock_entry(entry);
+
+	return promisc;
+}
+
+size_t odp_pktio_mac_addr(odp_pktio_t id, void *mac_addr,
+		       size_t addr_size)
+{
+	pktio_entry_t *entry;
+
+	if (addr_size < ETH_ALEN)
+		return 0;
+
+	entry = get_pktio_entry(id);
+	if (entry == NULL) {
+		ODP_DBG("pktio entry %d does not exist\n", id);
+		return 0;
+	}
+
+	lock_entry(entry);
+
+	if (odp_unlikely(is_free(entry))) {
+		unlock_entry(entry);
+		ODP_DBG("already freed pktio\n");
+		return -1;
+	}
+
+	rte_eth_macaddr_get(entry->s.pkt_dpdk.portid,
+			    (struct ether_addr *)mac_addr);
+	unlock_entry(entry);
+
+	return ETH_ALEN;
+}
+
 int odp_pktio_get_mac_addr(odp_pktio_t id, unsigned char *mac_addr)
 {
-	pktio_entry_t *pktio_entry = get_entry(id);
+	pktio_entry_t *pktio_entry = get_pktio_entry(id);
 	if (!pktio_entry) {
 		ODP_ERR("Invalid odp_pktio_t value\n");
 		return -1;
