[dpdk-dev,1/3] drivers/net: add support for IF-MIB and EtherLike-MIB for e1000

Message ID 20170522143202.22424-2-michalx.k.jastrzebski@intel.com (mailing list archive)
State Changes Requested, archived
Delegated to: Ferruh Yigit
Headers

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation success Compilation OK

Commit Message

Michal Jastrzebski May 22, 2017, 2:32 p.m. UTC
  If-MIB xstats:
ifNumber
ifIndex
ifType
ifMtu
ifSpeed
ifPhysAddress
ifOperStatus
ifLastChange
ifHighSpeed
ifConnectorPresent
ifCounterDiscontinuityTime

EtherLike-MIB xstats:
dot3PauseOperMode
dot3StatsDuplexStatus
dot3StatsRateControlAbility
dot3StatsRateControlStatus
dot3ControlFunctionsSupported

Signed-off-by: Piotr Azarewicz <piotrx.t.azarewicz@intel.com>
Signed-off-by: Michal Jastrzebski <michalx.k.jastrzebski@intel.com>
---
 drivers/net/e1000/e1000_ethdev.h |   59 ++++++++
 drivers/net/e1000/igb_ethdev.c   |  296 ++++++++++++++++++++++++++++++++++----
 2 files changed, 331 insertions(+), 24 deletions(-)
  

Comments

Pattan, Reshma May 22, 2017, 4:34 p.m. UTC | #1
Hi,

Can you add the description to the commit message, describing what has been done.

General doubt I have , I see all IF-MIB and Ether-Like-MIB attributes are added as Xstats.
But most of  IF-MIB attributes are not stats, instead they are information about the interface/port.
So I guess such attributes should be displayed using separate method?   Everything being displayed as xstats might not be correct.

> ---
> 
> +#define E1000_MIB_IF_TYPE_ETHERNETCSMACD	6
> +
> +enum e1000_mib_truth_value {
> +	e1000_mib_truth_true = 1,
> +	e1000_mib_truth_false
> +};
> +

All enums should be in capital as per coding guidelines. Similarly correct author enums too.
We no need to have enum identifier, just enumerator list should be suffice like below. 
So you can check all enumerations added newly and correct them?
Ex:
enum
{  
enumerator-list  
}  

> +/* IF-MIB statistics */
> +struct e1000_if_mib_stats {
> +	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_connector_present;		/* ifConnectorPresent */
> +	uint64_t if_counter_discontinuity_time;	/*
> ifCounterDiscontinuityTime */
> +};
> +

The comments should be inside /**<  Here the comment goes. */
Refer other files to see how it is done.

> +#define E1000_DOT3_CF_PAUSE	(1 << 0) /* PAUSE command
> implemented */
> +#define E1000_DOT3_CF_MPCP	(1 << 1) /* MPCP implemented */
> +#define E1000_DOT3_CF_PFC	(1 << 2) /* PFC implemented */
> +

The comments should be inside /**<  Here the comment goes. */

> +	uint64_t dot3_stats_rate_control_ability;
> +	/* dot3StatsRateControlAbility */
> +	uint64_t dot3_stats_rate_control_status;/*
> dot3StatsRateControlStatus */
> +	uint64_t dot3_control_functions_supported;
> +	/* dot3ControlFunctionsSupported */
> +};
> +

The comments line should go on top of the variables.

>  #define E1000_DEV_PRIVATE(adapter) \
> diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
> index e1702d8..705b591 100644
> --- a/drivers/net/e1000/igb_ethdev.c

Can you rename igb_if_mib_strings to rte_ igb_if_mib_strings and igb_if_mib_strings to rte_ igb_if_mib_strings? Similar to other stats/xstats.

eth_igb_stats_reset(), inside this function  we might not need below piece of code, as below piece of code you have already added to 
eth_igb_xstats_reset().

> stats->if_speed = (data->dev_link.link_speed < (UINT32_MAX / 1000000)) ?
>			(data->dev_link.link_speed * 1000000) : UINT32_MAX;

Can you clarify this link speed calculation logic

>	stats->if_last_change = adapter->if_last_change /
>			(rte_get_tsc_hz() * 100);

Can you clarify this logic?

Thanks,
Reshma
  
Wenzhuo Lu May 23, 2017, 5:53 a.m. UTC | #2
Hi Michal,

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Pattan, Reshma
> Sent: Tuesday, May 23, 2017 12:35 AM
> To: Jastrzebski, MichalX K; dev@dpdk.org
> Cc: Jain, Deepak K; Van Haaren, Harry; Azarewicz, PiotrX T
> Subject: Re: [dpdk-dev] [PATCH 1/3] drivers/net: add support for IF-MIB and
> EtherLike-MIB for e1000
> 
> Hi,
> 
> Can you add the description to the commit message, describing what has
> been done.
> 
> General doubt I have , I see all IF-MIB and Ether-Like-MIB attributes are
> added as Xstats.
> But most of  IF-MIB attributes are not stats, instead they are information
> about the interface/port.
> So I guess such attributes should be displayed using separate method?
> Everything being displayed as xstats might not be correct.
The same question as Reshma. Seems most of the added parameters (if not all) are not stats.
  
Radu Nicolau June 20, 2017, 11:38 a.m. UTC | #3
Hi,


On 5/23/2017 6:53 AM, Lu, Wenzhuo wrote:
> Hi Michal,
>
>> -----Original Message-----
>> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Pattan, Reshma
>> Sent: Tuesday, May 23, 2017 12:35 AM
>> To: Jastrzebski, MichalX K; dev@dpdk.org
>> Cc: Jain, Deepak K; Van Haaren, Harry; Azarewicz, PiotrX T
>> Subject: Re: [dpdk-dev] [PATCH 1/3] drivers/net: add support for IF-MIB and
>> EtherLike-MIB for e1000
>>
>> Hi,
>>
>> Can you add the description to the commit message, describing what has
>> been done.
>>
>> General doubt I have , I see all IF-MIB and Ether-Like-MIB attributes are
>> added as Xstats.
>> But most of  IF-MIB attributes are not stats, instead they are information
>> about the interface/port.
>> So I guess such attributes should be displayed using separate method?
>> Everything being displayed as xstats might not be correct.
> The same question as Reshma. Seems most of the added parameters (if not all) are not stats.

Yes, they are indeed mostly information rather than actual statistics, 
but I would say it's a better choice to have them in the xstats rather 
than add a new API.
  

Patch

diff --git a/drivers/net/e1000/e1000_ethdev.h b/drivers/net/e1000/e1000_ethdev.h
index 8352d0a..d242990 100644
--- a/drivers/net/e1000/e1000_ethdev.h
+++ b/drivers/net/e1000/e1000_ethdev.h
@@ -254,6 +254,62 @@  struct e1000_filter_info {
 	struct e1000_2tuple_filter_list twotuple_list;
 };
 
+#define E1000_MIB_IF_TYPE_ETHERNETCSMACD	6
+
+enum e1000_mib_truth_value {
+	e1000_mib_truth_true = 1,
+	e1000_mib_truth_false
+};
+
+/* IF-MIB statistics */
+struct e1000_if_mib_stats {
+	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_connector_present;		/* ifConnectorPresent */
+	uint64_t if_counter_discontinuity_time;	/* ifCounterDiscontinuityTime */
+};
+
+enum e1000_dot3_pause_oper_mode {
+	e1000_dot3_pause_disabled = 1,
+	e1000_dot3_pause_enabledxmit,
+	e1000_dot3_pause_enabledrcv,
+	e1000_dot3_pause_enabledxmitandrcv
+};
+
+enum e1000_dot3_stats_duplex_status {
+	e1000_dot3_duplex_unknown = 1,
+	e1000_dot3_duplex_halfduplex,
+	e1000_dot3_duplex_fullduplex
+};
+
+enum e1000_dot3_stats_rate_control_status {
+	e1000_dot3_rate_control_off = 1,
+	e1000_dot3_rate_control_on,
+	e1000_dot3_rate_control_unknown
+};
+
+#define E1000_DOT3_CF_PAUSE	(1 << 0) /* PAUSE command implemented */
+#define E1000_DOT3_CF_MPCP	(1 << 1) /* MPCP implemented */
+#define E1000_DOT3_CF_PFC	(1 << 2) /* PFC implemented */
+
+/* Ethernet-like-MIB statistics */
+struct e1000_ether_like_mib_stats {
+	uint64_t dot3_pause_oper_mode;		/* dot3PauseOperMode */
+	uint64_t dot3_stats_duplex_status;	/* dot3StatsDuplexStatus */
+	uint64_t dot3_stats_rate_control_ability;
+	/* dot3StatsRateControlAbility */
+	uint64_t dot3_stats_rate_control_status;/* dot3StatsRateControlStatus */
+	uint64_t dot3_control_functions_supported;
+	/* dot3ControlFunctionsSupported */
+};
+
 /*
  * Structure to store private data for each driver instance (for each port).
  */
@@ -268,6 +324,9 @@  struct e1000_adapter {
 	struct rte_timecounter  systime_tc;
 	struct rte_timecounter  rx_tstamp_tc;
 	struct rte_timecounter  tx_tstamp_tc;
+	uint64_t                sys_up_time_start;
+	uint64_t                if_last_change;
+	uint64_t                if_counter_discontinuity_time;
 };
 
 #define E1000_DEV_PRIVATE(adapter) \
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index e1702d8..705b591 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -560,6 +560,45 @@  struct rte_igb_xstats_name_off {
 #define IGBVF_NB_XSTATS (sizeof(rte_igbvf_stats_strings) / \
 		sizeof(rte_igbvf_stats_strings[0]))
 
+static const struct rte_igb_xstats_name_off igb_if_mib_strings[] = {
+	{"ifNumber", offsetof(struct e1000_if_mib_stats, if_number)},
+	{"ifIndex", offsetof(struct e1000_if_mib_stats, if_index)},
+	{"ifType", offsetof(struct e1000_if_mib_stats, if_type)},
+	{"ifMtu", offsetof(struct e1000_if_mib_stats, if_mtu)},
+	{"ifSpeed", offsetof(struct e1000_if_mib_stats, if_speed)},
+	{"ifPhysAddress", offsetof(struct e1000_if_mib_stats, if_phys_address)},
+	{"ifOperStatus", offsetof(struct e1000_if_mib_stats, if_oper_status)},
+	{"ifLastChange", offsetof(struct e1000_if_mib_stats, if_last_change)},
+	{"ifHighSpeed", offsetof(struct e1000_if_mib_stats, if_high_speed)},
+	{"ifConnectorPresent", offsetof(struct e1000_if_mib_stats,
+			if_connector_present)},
+	{"ifCounterDiscontinuityTime", offsetof(struct e1000_if_mib_stats,
+			if_counter_discontinuity_time)},
+};
+
+#define IGB_NB_IF_MIB_XSTATS (sizeof(igb_if_mib_strings) / \
+		sizeof(igb_if_mib_strings[0]))
+
+static const struct rte_igb_xstats_name_off igb_ether_like_mib_strings[] = {
+	{"dot3PauseOperMode", offsetof(struct e1000_ether_like_mib_stats,
+			dot3_pause_oper_mode)},
+	{"dot3StatsDuplexStatus", offsetof(struct e1000_ether_like_mib_stats,
+			dot3_stats_duplex_status)},
+	{"dot3StatsRateControlAbility", offsetof(
+			struct e1000_ether_like_mib_stats,
+			dot3_stats_rate_control_ability)},
+	{"dot3StatsRateControlStatus", offsetof(
+			struct e1000_ether_like_mib_stats,
+			dot3_stats_rate_control_status)},
+	{"dot3ControlFunctionsSupported", offsetof(
+			struct e1000_ether_like_mib_stats,
+			dot3_control_functions_supported)},
+};
+
+#define IGB_NB_ETHER_LIKE_MIB_XSTATS \
+		(sizeof(igb_ether_like_mib_strings) / \
+		sizeof(igb_ether_like_mib_strings[0]))
+
 /**
  * Atomically reads the link status information from global
  * structure rte_eth_dev.
@@ -896,6 +935,11 @@  struct rte_igb_xstats_name_off {
 		     eth_dev->data->port_id, pci_dev->id.vendor_id,
 		     pci_dev->id.device_id);
 
+	/* indicate sysUpTime start */
+	adapter->sys_up_time_start = rte_rdtsc();
+	adapter->if_last_change = 0;
+	adapter->if_counter_discontinuity_time = 0;
+
 	rte_intr_callback_register(&pci_dev->intr_handle,
 				   eth_igb_interrupt_handler,
 				   (void *)eth_dev);
@@ -1059,6 +1103,11 @@  struct rte_igb_xstats_name_off {
 		     eth_dev->data->port_id, pci_dev->id.vendor_id,
 		     pci_dev->id.device_id, "igb_mac_82576_vf");
 
+	/* indicate sysUpTime start */
+	adapter->sys_up_time_start = rte_rdtsc();
+	adapter->if_last_change = 0;
+	adapter->if_counter_discontinuity_time = 0;
+
 	intr_handle = &pci_dev->intr_handle;
 	rte_intr_callback_register(intr_handle,
 				   eth_igbvf_interrupt_handler, eth_dev);
@@ -1830,12 +1879,17 @@  static int eth_igbvf_pci_remove(struct rte_pci_device *pci_dev)
 {
 	struct e1000_hw_stats *hw_stats =
 			E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+	struct e1000_adapter *adapter =
+		E1000_DEV_PRIVATE(dev->data->dev_private);
 
 	/* HW registers are cleared on read */
 	eth_igb_stats_get(dev, NULL);
 
 	/* Reset software totals */
 	memset(hw_stats, 0, sizeof(*hw_stats));
+
+	adapter->if_counter_discontinuity_time =
+			rte_rdtsc() - adapter->sys_up_time_start;
 }
 
 static void
@@ -1843,31 +1897,138 @@  static int eth_igbvf_pci_remove(struct rte_pci_device *pci_dev)
 {
 	struct e1000_hw_stats *stats =
 			E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+	struct e1000_adapter *adapter =
+		E1000_DEV_PRIVATE(dev->data->dev_private);
 
 	/* HW registers are cleared on read */
 	eth_igb_xstats_get(dev, NULL, IGB_NB_XSTATS);
 
 	/* Reset software totals */
 	memset(stats, 0, sizeof(*stats));
+
+	adapter->if_counter_discontinuity_time =
+			rte_rdtsc() - adapter->sys_up_time_start;
+}
+
+static unsigned int
+igb_xstats_calc_num(void)
+{
+	return IGB_NB_XSTATS + IGB_NB_IF_MIB_XSTATS +
+		IGB_NB_ETHER_LIKE_MIB_XSTATS;
 }
 
 static int eth_igb_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 	struct rte_eth_xstat_name *xstats_names,
 	__rte_unused unsigned int size)
 {
-	unsigned i;
+	unsigned int i, count = 0;
 
 	if (xstats_names == NULL)
-		return IGB_NB_XSTATS;
+		return igb_xstats_calc_num();
 
 	/* Note: limit checked in rte_eth_xstats_names() */
 
 	for (i = 0; i < IGB_NB_XSTATS; i++) {
-		snprintf(xstats_names[i].name, sizeof(xstats_names[i].name),
+		snprintf(xstats_names[count].name,
+			sizeof(xstats_names[count].name),
 			 "%s", rte_igb_stats_strings[i].name);
+		count++;
+	}
+
+	/* Get stats from IF-MIB objects */
+	for (i = 0; i < IGB_NB_IF_MIB_XSTATS; i++) {
+		snprintf(xstats_names[count].name,
+			sizeof(xstats_names[count].name),
+			 "%s", igb_if_mib_strings[i].name);
+		count++;
+	}
+
+	/* Get stats from Ethernet-like-MIB objects */
+	for (i = 0; i < IGB_NB_ETHER_LIKE_MIB_XSTATS; i++) {
+		snprintf(xstats_names[count].name,
+			sizeof(xstats_names[count].name),
+			 "%s", igb_ether_like_mib_strings[i].name);
+		count++;
 	}
 
-	return IGB_NB_XSTATS;
+	return count;
+}
+
+static void
+igb_read_if_mib(struct rte_eth_dev *dev, struct e1000_if_mib_stats *stats)
+{
+	struct rte_eth_dev_data *data = dev->data;
+	struct rte_device *device = dev->device;
+	struct e1000_adapter *adapter =
+			E1000_DEV_PRIVATE(dev->data->dev_private);
+
+	stats->if_number = rte_eth_dev_count();
+	stats->if_index = data->port_id + 1;
+	stats->if_type = E1000_MIB_IF_TYPE_ETHERNETCSMACD;
+	stats->if_mtu = data->mtu;
+	stats->if_speed = (data->dev_link.link_speed < (UINT32_MAX / 1000000)) ?
+			(data->dev_link.link_speed * 1000000) : UINT32_MAX;
+	stats->if_phys_address = 0;
+	ether_addr_copy(data->mac_addrs,
+			(struct ether_addr *)&stats->if_phys_address);
+	stats->if_oper_status = data->dev_link.link_status ?
+			e1000_mib_truth_true : e1000_mib_truth_false;
+	stats->if_last_change = adapter->if_last_change /
+			(rte_get_tsc_hz() * 100);
+	stats->if_high_speed = data->dev_link.link_speed;
+	if (device->devargs)
+		stats->if_connector_present =
+				(device->devargs->type == RTE_DEVTYPE_VIRTUAL) ?
+						e1000_mib_truth_false :
+						e1000_mib_truth_true;
+	else
+		stats->if_connector_present = 0;
+	stats->if_counter_discontinuity_time =
+			adapter->if_counter_discontinuity_time /
+			(rte_get_tsc_hz() * 100);
+}
+
+static void
+igb_read_ether_like_mib(struct rte_eth_dev *dev,
+		struct e1000_ether_like_mib_stats *stats)
+{
+	struct rte_eth_dev_data *data = dev->data;
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	switch (hw->fc.current_mode) {
+	case e1000_fc_none:
+		stats->dot3_pause_oper_mode = e1000_dot3_pause_disabled;
+		break;
+	case e1000_fc_rx_pause:
+		stats->dot3_pause_oper_mode = e1000_dot3_pause_enabledrcv;
+		break;
+	case e1000_fc_tx_pause:
+		stats->dot3_pause_oper_mode = e1000_dot3_pause_enabledxmit;
+		break;
+	case e1000_fc_full:
+		stats->dot3_pause_oper_mode =
+				e1000_dot3_pause_enabledxmitandrcv;
+		break;
+	default:
+		stats->dot3_pause_oper_mode = 0;
+		break;
+	}
+
+	switch (data->dev_link.link_duplex) {
+	case ETH_LINK_FULL_DUPLEX:
+		stats->dot3_stats_duplex_status = e1000_dot3_duplex_fullduplex;
+		break;
+	case ETH_LINK_HALF_DUPLEX:
+		stats->dot3_stats_duplex_status = e1000_dot3_duplex_halfduplex;
+		break;
+	default:
+		stats->dot3_stats_duplex_status = e1000_dot3_duplex_unknown;
+		break;
+	}
+
+	stats->dot3_stats_rate_control_ability = e1000_mib_truth_false;
+	stats->dot3_stats_rate_control_status = e1000_dot3_rate_control_off;
+	stats->dot3_control_functions_supported = E1000_DOT3_CF_PAUSE;
 }
 
 static int eth_igb_xstats_get_names_by_id(struct rte_eth_dev *dev,
@@ -1912,27 +2073,53 @@  static int eth_igb_xstats_get_names_by_id(struct rte_eth_dev *dev,
 	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	struct e1000_hw_stats *hw_stats =
 			E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
-	unsigned i;
+	struct e1000_if_mib_stats if_mib_stats;
+	struct e1000_ether_like_mib_stats ether_like_mib_stats;
+	unsigned int i, count;
 
-	if (n < IGB_NB_XSTATS)
-		return IGB_NB_XSTATS;
+	count = igb_xstats_calc_num();
+	if (n < count)
+		return count;
 
 	igb_read_stats_registers(hw, hw_stats);
 
+	igb_read_if_mib(dev, &if_mib_stats);
+	igb_read_ether_like_mib(dev, &ether_like_mib_stats);
+
 	/* If this is a reset xstats is NULL, and we have cleared the
 	 * registers by reading them.
 	 */
 	if (!xstats)
 		return 0;
 
+	count = 0;
+
 	/* Extended stats */
 	for (i = 0; i < IGB_NB_XSTATS; i++) {
-		xstats[i].id = i;
-		xstats[i].value = *(uint64_t *)(((char *)hw_stats) +
+		xstats[count].id = count;
+		xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
 			rte_igb_stats_strings[i].offset);
+		count++;
+	}
+
+	/* Get stats from IF-MIB objects */
+	for (i = 0; i < IGB_NB_IF_MIB_XSTATS; i++) {
+		xstats[count].value = *(uint64_t *)(((char *)&if_mib_stats) +
+			igb_if_mib_strings[i].offset);
+		xstats[count].id = count;
+		count++;
 	}
 
-	return IGB_NB_XSTATS;
+	/* Get stats from Ethernet-like-MIB objects */
+	for (i = 0; i < IGB_NB_ETHER_LIKE_MIB_XSTATS; i++) {
+		xstats[count].value =
+			*(uint64_t *)(((char *)&ether_like_mib_stats) +
+			igb_ether_like_mib_strings[i].offset);
+		xstats[count].id = count;
+		count++;
+	}
+
+	return count;
 }
 
 static int
@@ -2022,19 +2209,46 @@  static int eth_igb_xstats_get_names_by_id(struct rte_eth_dev *dev,
 	    hw_stats->last_gotlbc, hw_stats->gotlbc);
 }
 
+static unsigned int
+igbvf_xstats_calc_num(void)
+{
+	return IGBVF_NB_XSTATS + IGB_NB_IF_MIB_XSTATS +
+		IGB_NB_ETHER_LIKE_MIB_XSTATS;
+}
+
 static int eth_igbvf_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 				     struct rte_eth_xstat_name *xstats_names,
 				     __rte_unused unsigned limit)
 {
-	unsigned i;
+	unsigned int i, count = 0;
 
-	if (xstats_names != NULL)
-		for (i = 0; i < IGBVF_NB_XSTATS; i++) {
-			snprintf(xstats_names[i].name,
-				sizeof(xstats_names[i].name), "%s",
-				rte_igbvf_stats_strings[i].name);
-		}
-	return IGBVF_NB_XSTATS;
+	if (xstats_names == NULL)
+		return igbvf_xstats_calc_num();
+
+	for (i = 0; i < IGBVF_NB_XSTATS; i++) {
+		snprintf(xstats_names[count].name,
+			sizeof(xstats_names[count].name), "%s",
+			rte_igbvf_stats_strings[i].name);
+		count++;
+	}
+
+	/* Get stats from IF-MIB objects */
+	for (i = 0; i < IGB_NB_IF_MIB_XSTATS; i++) {
+		snprintf(xstats_names[count].name,
+			sizeof(xstats_names[count].name),
+			 "%s", igb_if_mib_strings[i].name);
+		count++;
+	}
+
+	/* Get stats from Ethernet-like-MIB objects */
+	for (i = 0; i < IGB_NB_ETHER_LIKE_MIB_XSTATS; i++) {
+		snprintf(xstats_names[count].name,
+			sizeof(xstats_names[count].name),
+			 "%s", igb_ether_like_mib_strings[i].name);
+		count++;
+	}
+
+	return count;
 }
 
 static int
@@ -2044,23 +2258,49 @@  static int eth_igbvf_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	struct e1000_vf_stats *hw_stats = (struct e1000_vf_stats *)
 			E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
-	unsigned i;
+	struct e1000_if_mib_stats if_mib_stats;
+	struct e1000_ether_like_mib_stats ether_like_mib_stats;
+	unsigned int i, count;
 
-	if (n < IGBVF_NB_XSTATS)
-		return IGBVF_NB_XSTATS;
+	count = igbvf_xstats_calc_num();
+	if (n < count)
+		return count;
 
 	igbvf_read_stats_registers(hw, hw_stats);
 
+	igb_read_if_mib(dev, &if_mib_stats);
+	igb_read_ether_like_mib(dev, &ether_like_mib_stats);
+
 	if (!xstats)
 		return 0;
 
+	count = 0;
+
 	for (i = 0; i < IGBVF_NB_XSTATS; i++) {
-		xstats[i].id = i;
-		xstats[i].value = *(uint64_t *)(((char *)hw_stats) +
+		xstats[count].id = count;
+		xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
 			rte_igbvf_stats_strings[i].offset);
+		count++;
 	}
 
-	return IGBVF_NB_XSTATS;
+	/* Get stats from IF-MIB objects */
+	for (i = 0; i < IGB_NB_IF_MIB_XSTATS; i++) {
+		xstats[count].value = *(uint64_t *)(((char *)&if_mib_stats) +
+			igb_if_mib_strings[i].offset);
+		xstats[count].id = count;
+		count++;
+	}
+
+	/* Get stats from Ethernet-like-MIB objects */
+	for (i = 0; i < IGB_NB_ETHER_LIKE_MIB_XSTATS; i++) {
+		xstats[count].value =
+			*(uint64_t *)(((char *)&ether_like_mib_stats) +
+			igb_ether_like_mib_strings[i].offset);
+		xstats[count].id = count;
+		count++;
+	}
+
+	return count;
 }
 
 static void
@@ -2086,6 +2326,8 @@  static int eth_igbvf_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 {
 	struct e1000_vf_stats *hw_stats = (struct e1000_vf_stats*)
 			E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+	struct e1000_adapter *adapter =
+		E1000_DEV_PRIVATE(dev->data->dev_private);
 
 	/* Sync HW register to the last stats */
 	eth_igbvf_stats_get(dev, NULL);
@@ -2093,6 +2335,9 @@  static int eth_igbvf_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 	/* reset HW current stats*/
 	memset(&hw_stats->gprc, 0, sizeof(*hw_stats) -
 	       offsetof(struct e1000_vf_stats, gprc));
+
+	adapter->if_counter_discontinuity_time =
+			rte_rdtsc() - adapter->sys_up_time_start;
 }
 
 static int
@@ -2338,6 +2583,8 @@  static int eth_igbvf_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 {
 	struct e1000_hw *hw =
 		E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct e1000_adapter *adapter =
+		E1000_DEV_PRIVATE(dev->data->dev_private);
 	struct rte_eth_link link, old;
 	int link_check, count;
 
@@ -2406,6 +2653,7 @@  static int eth_igbvf_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 		return -1;
 
 	/* changed */
+	adapter->if_last_change = rte_rdtsc() - adapter->sys_up_time_start;
 	return 0;
 }