diff --git a/lib/Makefile b/lib/Makefile
index 07e1fd0..aa2be5b 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -35,6 +35,8 @@ DIRS-y += librte_compat
 DIRS-$(CONFIG_RTE_LIBRTE_EAL) += librte_eal
 DIRS-$(CONFIG_RTE_LIBRTE_RING) += librte_ring
 DEPDIRS-librte_ring := librte_eal
+DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics
+DEPDIRS-librte_metrics := librte_eal
 DIRS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += librte_mempool
 DEPDIRS-librte_mempool := librte_eal librte_ring
 DIRS-$(CONFIG_RTE_LIBRTE_MBUF) += librte_mbuf
@@ -46,7 +48,7 @@ DEPDIRS-librte_cfgfile := librte_eal
 DIRS-$(CONFIG_RTE_LIBRTE_CMDLINE) += librte_cmdline
 DEPDIRS-librte_cmdline := librte_eal
 DIRS-$(CONFIG_RTE_LIBRTE_ETHER) += librte_ether
-DEPDIRS-librte_ether := librte_net librte_eal librte_mempool librte_ring
+DEPDIRS-librte_ether := librte_net librte_eal librte_mempool librte_ring librte_metrics
 DEPDIRS-librte_ether += librte_mbuf
 DIRS-$(CONFIG_RTE_LIBRTE_CRYPTODEV) += librte_cryptodev
 DEPDIRS-librte_cryptodev := librte_eal librte_mempool librte_ring librte_mbuf
@@ -70,8 +72,6 @@ DEPDIRS-librte_ip_frag := librte_eal librte_mempool librte_mbuf librte_ether
 DEPDIRS-librte_ip_frag += librte_hash
 DIRS-$(CONFIG_RTE_LIBRTE_JOBSTATS) += librte_jobstats
 DEPDIRS-librte_jobstats := librte_eal
-DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics
-DEPDIRS-librte_metrics := librte_eal
 DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats
 DEPDIRS-librte_bitratestats := librte_eal librte_metrics librte_ether
 DIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += librte_latencystats
diff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile
index a5bd108..8dd438a 100644
--- a/lib/librte_eal/common/Makefile
+++ b/lib/librte_eal/common/Makefile
@@ -40,7 +40,7 @@ INC += rte_string_fns.h rte_version.h
 INC += rte_eal_memconfig.h rte_malloc_heap.h
 INC += rte_hexdump.h rte_devargs.h rte_bus.h rte_dev.h rte_vdev.h
 INC += rte_pci_dev_feature_defs.h rte_pci_dev_features.h
-INC += rte_malloc.h rte_keepalive.h rte_time.h
+INC += rte_malloc.h rte_keepalive.h rte_time.h rte_clock.h
 
 GENERIC_INC := rte_atomic.h rte_byteorder.h rte_cycles.h rte_prefetch.h
 GENERIC_INC += rte_spinlock.h rte_memcpy.h rte_cpuflags.h rte_rwlock.h
diff --git a/lib/librte_eal/common/include/rte_clock.h b/lib/librte_eal/common/include/rte_clock.h
new file mode 100644
index 0000000..8b22a37
--- /dev/null
+++ b/lib/librte_eal/common/include/rte_clock.h
@@ -0,0 +1,68 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2017-2018 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _RTE_CLOCK_H_
+#define _RTE_CLOCK_H_
+
+/**
+ * @file
+ *
+ * Retrieves the time of the monotonic clock.
+ */
+#include <time.h>
+
+struct rte_timespec {
+	time_t   tv_sec;        /* seconds */
+	long     tv_nsec;       /* nanoseconds */
+};
+
+/**
+ * Gets the time of the monotonic clock.
+ *
+ * @return
+ *   The number of cycles
+ */
+static int
+rte_clock_monotonic_gettime(struct rte_timespec *time)
+{
+	if (time == NULL)
+		return -1;
+
+	struct timespec *sp = (struct timespec *)time;
+	if (clock_gettime(CLOCK_MONOTONIC, sp) != 0)
+		return -1;
+
+	return 0;
+}
+
+#endif /* _RTE_CLOCK_H_ */
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 71a576c..14581d0 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -64,6 +64,10 @@
 #include <rte_errno.h>
 #include <rte_spinlock.h>
 #include <rte_string_fns.h>
+#include <rte_cycles.h>
+#include <rte_metrics.h>
+#include <rte_clock.h>
+#include <rte_time.h>
 
 #include "rte_ether.h"
 #include "rte_ethdev.h"
@@ -118,7 +122,8 @@ static const struct rte_eth_xstats_name_off rte_txq_stats_strings[] = {
 #define RTE_NB_TXQ_STATS (sizeof(rte_txq_stats_strings) /	\
 		sizeof(rte_txq_stats_strings[0]))
 
-
+#define RTE_MIB_ATTR_NAME_SIZE 32
+#define RTE_IF_TYPE_ETHERNETCSMACD 6
 /**
  * The user application callback description.
  *
@@ -139,6 +144,11 @@ enum {
 	STAT_QMAP_RX
 };
 
+enum {
+	OPER_STATUS_UP = 1,
+	OPER_STATUS_DOWN
+};
+
 uint8_t
 rte_eth_find_next(uint8_t port_id)
 {
@@ -218,6 +228,7 @@ rte_eth_dev_allocate(const char *name)
 {
 	uint8_t port_id;
 	struct rte_eth_dev *eth_dev;
+	struct rte_timespec tsp;
 
 	port_id = rte_eth_dev_find_free_port();
 	if (port_id == RTE_MAX_ETHPORTS) {
@@ -239,6 +250,13 @@ rte_eth_dev_allocate(const char *name)
 	snprintf(eth_dev->data->name, sizeof(eth_dev->data->name), "%s", name);
 	eth_dev->data->port_id = port_id;
 	eth_dev->data->mtu = ETHER_MTU;
+	if (rte_clock_monotonic_gettime(&tsp) != 0) {
+		RTE_PMD_DEBUG_TRACE("Failed to get monotonic clock time: "
+				"%s\n", __func__);
+		return NULL;
+	}
+	eth_dev->data->sys_up_time_start =
+		tsp.tv_sec * NSEC_PER_SEC + tsp.tv_nsec;
 
 	return eth_dev;
 }
@@ -898,6 +916,7 @@ rte_eth_dev_start(uint8_t port_id)
 {
 	struct rte_eth_dev *dev;
 	int diag;
+	struct rte_timespec tsp;
 
 	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL);
 
@@ -923,6 +942,13 @@ rte_eth_dev_start(uint8_t port_id)
 	if (dev->data->dev_conf.intr_conf.lsc == 0) {
 		RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->link_update, -ENOTSUP);
 		(*dev->dev_ops->link_update)(dev, 0);
+		if (rte_clock_monotonic_gettime(&tsp) != 0) {
+			RTE_PMD_DEBUG_TRACE("Failed to get monotonic clock time"
+				": %s\n", __func__);
+			return -1;
+		}
+		dev->data->if_last_change = tsp.tv_sec * NSEC_PER_SEC +
+				tsp.tv_nsec - dev->data->sys_up_time_start;
 	}
 	return 0;
 }
@@ -1295,6 +1321,7 @@ void
 rte_eth_link_get(uint8_t port_id, struct rte_eth_link *eth_link)
 {
 	struct rte_eth_dev *dev;
+	struct rte_timespec tsp;
 
 	RTE_ETH_VALID_PORTID_OR_RET(port_id);
 	dev = &rte_eth_devices[port_id];
@@ -1305,6 +1332,12 @@ rte_eth_link_get(uint8_t port_id, struct rte_eth_link *eth_link)
 		RTE_FUNC_PTR_OR_RET(*dev->dev_ops->link_update);
 		(*dev->dev_ops->link_update)(dev, 1);
 		*eth_link = dev->data->dev_link;
+
+		if (rte_clock_monotonic_gettime(&tsp) != 0)
+			RTE_PMD_DEBUG_TRACE("Failed to get monotonic clock time"
+				": %s\n", __func__);
+		dev->data->if_last_change = tsp.tv_sec * NSEC_PER_SEC +
+			tsp.tv_nsec - dev->data->sys_up_time_start;
 	}
 }
 
@@ -1312,6 +1345,7 @@ void
 rte_eth_link_get_nowait(uint8_t port_id, struct rte_eth_link *eth_link)
 {
 	struct rte_eth_dev *dev;
+	struct rte_timespec tsp;
 
 	RTE_ETH_VALID_PORTID_OR_RET(port_id);
 	dev = &rte_eth_devices[port_id];
@@ -1322,6 +1356,14 @@ rte_eth_link_get_nowait(uint8_t port_id, struct rte_eth_link *eth_link)
 		RTE_FUNC_PTR_OR_RET(*dev->dev_ops->link_update);
 		(*dev->dev_ops->link_update)(dev, 0);
 		*eth_link = dev->data->dev_link;
+
+		if (rte_clock_monotonic_gettime(&tsp) != 0) {
+			RTE_PMD_DEBUG_TRACE("Failed to get monotonic clock time"
+				": %s\n", __func__);
+			return -1;
+		}
+		dev->data->if_last_change = tsp.tv_sec * NSEC_PER_SEC +
+			tsp.tv_nsec - dev->data->sys_up_time_start;
 	}
 }
 
@@ -1345,12 +1387,20 @@ void
 rte_eth_stats_reset(uint8_t port_id)
 {
 	struct rte_eth_dev *dev;
+	struct rte_timespec tsp;
 
 	RTE_ETH_VALID_PORTID_OR_RET(port_id);
 	dev = &rte_eth_devices[port_id];
 
 	RTE_FUNC_PTR_OR_RET(*dev->dev_ops->stats_reset);
 	(*dev->dev_ops->stats_reset)(dev);
+
+	if (rte_clock_monotonic_gettime(&tsp) != 0) {
+		RTE_PMD_DEBUG_TRACE("Failed to get monotonic clock time: "
+				"%s\n", __func__);
+	}
+	dev->data->if_cntr_disc_time = tsp.tv_sec * NSEC_PER_SEC + tsp.tv_nsec -
+			dev->data->sys_up_time_start;
 	dev->data->rx_mbuf_alloc_failed = 0;
 }
 
@@ -1822,6 +1872,7 @@ void
 rte_eth_xstats_reset(uint8_t port_id)
 {
 	struct rte_eth_dev *dev;
+	struct rte_timespec tsp;
 
 	RTE_ETH_VALID_PORTID_OR_RET(port_id);
 	dev = &rte_eth_devices[port_id];
@@ -1829,6 +1880,13 @@ rte_eth_xstats_reset(uint8_t port_id)
 	/* implemented by the driver */
 	if (dev->dev_ops->xstats_reset != NULL) {
 		(*dev->dev_ops->xstats_reset)(dev);
+
+	if (rte_clock_monotonic_gettime(&tsp) != 0)
+		RTE_PMD_DEBUG_TRACE("Failed to get monotonic clock time: "
+				"%s\n", __func__);
+	dev->data->if_cntr_disc_time = tsp.tv_sec * NSEC_PER_SEC + tsp.tv_nsec -
+		dev->data->sys_up_time_start;
+
 		return;
 	}
 
@@ -3354,3 +3412,115 @@ rte_eth_dev_l2_tunnel_offload_set(uint8_t port_id,
 				-ENOTSUP);
 	return (*dev->dev_ops->l2_tunnel_offload_set)(dev, l2_tunnel, mask, en);
 }
+
+/* IF-MIB attributes*/
+struct rte_if_mib_attrs {
+	uint64_t if_number;			/* ifNumber */
+	uint64_t if_index;			/* ifIndex */
+	uint64_t if_type;			/* ifType */
+	uint64_t if_mtu;			/* ifMtu */
+	uint64_t if_speed;			/* ifSpeed */
+	uint64_t if_phys_address;		/* ifPhysAddress */
+	uint64_t if_oper_status;		/* ifOperStatus */
+	uint64_t if_last_change;		/* ifLastChange */
+	uint64_t if_high_speed;			/* ifHighSpeed */
+	uint64_t if_cnctr_present;		/* ifConnectorPresent */
+	uint64_t if_cntr_disc_time;	/* ifCounterDiscontinuityTime */
+};
+
+static struct rte_if_mib_attrs *if_mib_attrs;
+
+struct if_mib_attrs_nameoff {
+	char name[RTE_MIB_ATTR_NAME_SIZE];
+	unsigned int offset;
+};
+
+static const struct if_mib_attrs_nameoff if_mib_attrs_strings[] = {
+	{"ifNumber", offsetof(struct rte_if_mib_attrs, if_number)},
+	{"ifIndex", offsetof(struct rte_if_mib_attrs, if_index)},
+	{"ifType", offsetof(struct rte_if_mib_attrs, if_type)},
+	{"ifMtu", offsetof(struct rte_if_mib_attrs, if_mtu)},
+	{"ifSpeed", offsetof(struct rte_if_mib_attrs, if_speed)},
+	{"ifPhysAddress", offsetof(struct rte_if_mib_attrs, if_phys_address)},
+	{"ifOperStatus", offsetof(struct rte_if_mib_attrs, if_oper_status)},
+	{"ifLastChange", offsetof(struct rte_if_mib_attrs, if_last_change)},
+	{"ifHighSpeed", offsetof(struct rte_if_mib_attrs, if_high_speed)},
+	{"ifConnectorPresent", offsetof(struct rte_if_mib_attrs,
+		if_cnctr_present)},
+	{"ifCounterDiscontinuityTime", offsetof(struct rte_if_mib_attrs,
+		if_cntr_disc_time)},
+};
+
+#define NUM_IF_MIB_ATTRS (sizeof(if_mib_attrs_strings) / \
+	sizeof(if_mib_attrs_strings[0]))
+
+int
+rte_eth_ifmib_attr_init(void) {
+	if_mib_attrs = rte_zmalloc(NULL, sizeof(struct rte_if_mib_attrs),
+		RTE_CACHE_LINE_SIZE);
+
+	return 0;
+}
+
+int
+rte_eth_ifmib_attr_reg(uint8_t port_id) {
+
+	int idx;
+	unsigned int i;
+	uint64_t *attr_ptr = NULL;
+	const char *ptr_strings[NUM_IF_MIB_ATTRS] = {0};
+	struct rte_eth_dev *eth_dev;
+	struct rte_device *device;
+	struct rte_eth_dev_data *data;
+	uint64_t values[NUM_IF_MIB_ATTRS] = {0};
+
+	for (i = 0; i < NUM_IF_MIB_ATTRS; i++)
+		ptr_strings[i] = if_mib_attrs_strings[i].name;
+
+	/* register names with metrics library */
+	idx = rte_metrics_reg_names(ptr_strings, NUM_IF_MIB_ATTRS);
+
+	eth_dev = eth_dev_get(port_id);
+	data = eth_dev->data;
+	device = eth_dev->device;
+
+	/* implement if mib attributes */
+	if_mib_attrs->if_number = rte_eth_dev_count();
+
+	if_mib_attrs->if_index = data->port_id + 1;
+
+	if_mib_attrs->if_type = RTE_IF_TYPE_ETHERNETCSMACD;
+
+	if_mib_attrs->if_mtu = data->mtu;
+
+	if_mib_attrs->if_speed =
+			(data->dev_link.link_speed < (UINT32_MAX / 1000000)) ?
+			(data->dev_link.link_speed * 1000000) : UINT32_MAX;
+
+	if_mib_attrs->if_phys_address = 0;
+	ether_addr_copy(data->mac_addrs,
+		(struct ether_addr *)if_mib_attrs->if_phys_address);
+
+	if_mib_attrs->if_oper_status = data->dev_link.link_status ?
+					OPER_STATUS_UP : OPER_STATUS_DOWN;
+
+	if_mib_attrs->if_last_change = data->if_last_change;
+
+	if_mib_attrs->if_high_speed = data->dev_link.link_speed;
+
+	if_mib_attrs->if_cnctr_present =
+		(device->devargs->type == RTE_DEVTYPE_VIRTUAL) ?
+					OPER_STATUS_UP : OPER_STATUS_DOWN;
+
+	if_mib_attrs->if_cntr_disc_time = data->if_cntr_disc_time;
+
+	for (i = 0; i < NUM_IF_MIB_ATTRS; i++) {
+		attr_ptr = RTE_PTR_ADD(if_mib_attrs,
+					if_mib_attrs_strings[i].offset);
+		values[i] = *attr_ptr;
+	}
+	/* update values to metrics library */
+	rte_metrics_update_values(port_id, idx, values, NUM_IF_MIB_ATTRS);
+
+	return 0;
+}
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 1446540..7ddbc41 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -1674,6 +1674,10 @@ struct rte_eth_dev_data {
 	uint32_t dev_flags; /**< Capabilities */
 	enum rte_kernel_driver kdrv;    /**< Kernel driver passthrough */
 	int numa_node;  /**< NUMA node connection */
+	/** IF-MIB attributes ifLastChange and ifCounterDiscontinuityTime */
+	uint64_t sys_up_time_start;
+	uint64_t if_cntr_disc_time;
+	uint64_t if_last_change;
 };
 
 /** Device supports hotplug detach */
@@ -4375,6 +4379,9 @@ rte_eth_dev_get_port_by_name(const char *name, uint8_t *port_id);
 int
 rte_eth_dev_get_name_by_port(uint8_t port_id, char *name);
 
+int rte_eth_ifmib_attr_init(void);
+int rte_eth_ifmib_attr_reg(uint8_t port_id);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/librte_ether/rte_ethdev_pci.h b/lib/librte_ether/rte_ethdev_pci.h
index 69aab03..e6e757f 100644
--- a/lib/librte_ether/rte_ethdev_pci.h
+++ b/lib/librte_ether/rte_ethdev_pci.h
@@ -37,6 +37,7 @@
 #include <rte_malloc.h>
 #include <rte_pci.h>
 #include <rte_ethdev.h>
+#include <rte_cycles.h>
 
 /**
  * Copy pci device info to the Ethernet device data.
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 7d71a49..9dc9597 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -73,7 +73,6 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_ACL)            += --whole-archive
 _LDLIBS-$(CONFIG_RTE_LIBRTE_ACL)            += -lrte_acl
 _LDLIBS-$(CONFIG_RTE_LIBRTE_ACL)            += --no-whole-archive
 _LDLIBS-$(CONFIG_RTE_LIBRTE_JOBSTATS)       += -lrte_jobstats
-_LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS)        += -lrte_metrics
 _LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE)        += -lrte_bitratestats
 _LDLIBS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS)  += -lrte_latencystats
 _LDLIBS-$(CONFIG_RTE_LIBRTE_POWER)          += -lrte_power
@@ -95,6 +94,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_EVENTDEV)       += -lrte_eventdev
 _LDLIBS-$(CONFIG_RTE_LIBRTE_MEMPOOL)        += -lrte_mempool
 _LDLIBS-$(CONFIG_RTE_DRIVER_MEMPOOL_RING)   += -lrte_mempool_ring
 _LDLIBS-$(CONFIG_RTE_LIBRTE_RING)           += -lrte_ring
+_LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS)        += -lrte_metrics
 _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL)            += -lrte_eal
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE)        += -lrte_cmdline
 _LDLIBS-$(CONFIG_RTE_LIBRTE_REORDER)        += -lrte_reorder
