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

Message ID 1498470133-29788-1-git-send-email-radu.nicolau@intel.com (mailing list archive)
State Changes Requested, archived
Delegated to: Ferruh Yigit
Headers

Checks

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

Commit Message

Radu Nicolau June 26, 2017, 9:42 a.m. UTC
  From: Michal Jastrzebski <michalx.k.jastrzebski@intel.com>

If-MIB xstats:
ifNumber
ifIndex
ifType
ifMtu
ifSpeed
ifPhysAddress
ifOperStatus
ifLastChange
ifHighSpeed
ifConnectorPresent
ifCounterDiscontinuityTime

EtherLike-MIB xstats:
dot3PauseOperMode
dot3StatsDuplexStatus
dot3StatsRateControlAbility
dot3StatsRateControlStatus
dot3ControlFunctionsSupported

-updated in v2: coding style

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

Comments

Ferruh Yigit June 27, 2017, 11:08 a.m. UTC | #1
On 6/26/2017 10:42 AM, Radu Nicolau wrote:
> From: Michal Jastrzebski <michalx.k.jastrzebski@intel.com>
> 
> If-MIB xstats:
> ifNumber
> ifIndex
> ifType
> ifMtu
> ifSpeed
> ifPhysAddress
> ifOperStatus
> ifLastChange
> ifHighSpeed
> ifConnectorPresent
> ifCounterDiscontinuityTime
> 
> EtherLike-MIB xstats:
> dot3PauseOperMode
> dot3StatsDuplexStatus
> dot3StatsRateControlAbility
> dot3StatsRateControlStatus
> dot3ControlFunctionsSupported
> 
> -updated in v2: coding style
> 
> Signed-off-by: Piotr Azarewicz <piotrx.t.azarewicz@intel.com>
> Signed-off-by: Michal Jastrzebski <michalx.k.jastrzebski@intel.com>
> Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>

<...>

This patch implements MIBs for some Intel drivers using xstats, this is
easy way to get some information from PMDs.

But there was a outstanding comment to make this ethdev layer.

So I believe we have two options:

[1]
Each PMD implements MIBs using xstats, this is pragmatic solution and
each PMD can implement whichever MIBs they want.

[2]
Implement a ethdev layer API and add a new dev_ops to get MIBs, API can
use existing methods to get required information, and if it fails can
call dev_ops which can be similar to the xstats.
Because of API all PMDs can have a small amount of support by default
and they can implement dev_ops for more support.


Although 2) looks more generic and proper, I am not really sure if that
is overkill and if this worth to the effort and to have new API and
dev_ops, comparing current method is easy to implement, any comments?

Thanks,
ferruh
  
Bruce Richardson June 27, 2017, 11:21 a.m. UTC | #2
On Tue, Jun 27, 2017 at 12:08:56PM +0100, Ferruh Yigit wrote:
> On 6/26/2017 10:42 AM, Radu Nicolau wrote:
> > From: Michal Jastrzebski <michalx.k.jastrzebski@intel.com>
> > 
> > If-MIB xstats:
> > ifNumber
> > ifIndex
> > ifType
> > ifMtu
> > ifSpeed
> > ifPhysAddress
> > ifOperStatus
> > ifLastChange
> > ifHighSpeed
> > ifConnectorPresent
> > ifCounterDiscontinuityTime
> > 
> > EtherLike-MIB xstats:
> > dot3PauseOperMode
> > dot3StatsDuplexStatus
> > dot3StatsRateControlAbility
> > dot3StatsRateControlStatus
> > dot3ControlFunctionsSupported
> > 
> > -updated in v2: coding style
> > 
> > Signed-off-by: Piotr Azarewicz <piotrx.t.azarewicz@intel.com>
> > Signed-off-by: Michal Jastrzebski <michalx.k.jastrzebski@intel.com>
> > Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
> 
> <...>
> 
> This patch implements MIBs for some Intel drivers using xstats, this is
> easy way to get some information from PMDs.
> 
> But there was a outstanding comment to make this ethdev layer.
> 
> So I believe we have two options:
> 
> [1]
> Each PMD implements MIBs using xstats, this is pragmatic solution and
> each PMD can implement whichever MIBs they want.
> 
> [2]
> Implement a ethdev layer API and add a new dev_ops to get MIBs, API can
> use existing methods to get required information, and if it fails can
> call dev_ops which can be similar to the xstats.
> Because of API all PMDs can have a small amount of support by default
> and they can implement dev_ops for more support.
> 
> 
> Although 2) looks more generic and proper, I am not really sure if that
> is overkill and if this worth to the effort and to have new API and
> dev_ops, comparing current method is easy to implement, any comments?
> 

For 2, does the "use existing methods" include calling xstats? If so,
then we can just drop the requirement for 2 to have any new functions
implemented in the driver. Instead, have the information provided by
drivers in the normal xstats call, but have a new ethdev API to provide
that information to the app - basically hiding the xstats complexity
underneath.

/Bruce
  
Ferruh Yigit June 27, 2017, 11:36 a.m. UTC | #3
On 6/27/2017 12:21 PM, Bruce Richardson wrote:
> On Tue, Jun 27, 2017 at 12:08:56PM +0100, Ferruh Yigit wrote:
>> On 6/26/2017 10:42 AM, Radu Nicolau wrote:
>>> From: Michal Jastrzebski <michalx.k.jastrzebski@intel.com>
>>>
>>> If-MIB xstats:
>>> ifNumber
>>> ifIndex
>>> ifType
>>> ifMtu
>>> ifSpeed
>>> ifPhysAddress
>>> ifOperStatus
>>> ifLastChange
>>> ifHighSpeed
>>> ifConnectorPresent
>>> ifCounterDiscontinuityTime
>>>
>>> EtherLike-MIB xstats:
>>> dot3PauseOperMode
>>> dot3StatsDuplexStatus
>>> dot3StatsRateControlAbility
>>> dot3StatsRateControlStatus
>>> dot3ControlFunctionsSupported
>>>
>>> -updated in v2: coding style
>>>
>>> Signed-off-by: Piotr Azarewicz <piotrx.t.azarewicz@intel.com>
>>> Signed-off-by: Michal Jastrzebski <michalx.k.jastrzebski@intel.com>
>>> Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
>>
>> <...>
>>
>> This patch implements MIBs for some Intel drivers using xstats, this is
>> easy way to get some information from PMDs.
>>
>> But there was a outstanding comment to make this ethdev layer.
>>
>> So I believe we have two options:
>>
>> [1]
>> Each PMD implements MIBs using xstats, this is pragmatic solution and
>> each PMD can implement whichever MIBs they want.
>>
>> [2]
>> Implement a ethdev layer API and add a new dev_ops to get MIBs, API can
>> use existing methods to get required information, and if it fails can
>> call dev_ops which can be similar to the xstats.
>> Because of API all PMDs can have a small amount of support by default
>> and they can implement dev_ops for more support.
>>
>>
>> Although 2) looks more generic and proper, I am not really sure if that
>> is overkill and if this worth to the effort and to have new API and
>> dev_ops, comparing current method is easy to implement, any comments?
>>
> 
> For 2, does the "use existing methods" include calling xstats? If so,
> then we can just drop the requirement for 2 to have any new functions
> implemented in the driver. Instead, have the information provided by
> drivers in the normal xstats call, but have a new ethdev API to provide
> that information to the app - basically hiding the xstats complexity
> underneath.

I was thinking another dev_ops similar to xstats, but re-using xstats
can be better idea here.

so option 2 becomes:
[2] An eth_dev API to use existing APIs to get information from PMDs and
wrap MIBs related xstats calls.

But I believe if option 2 is overkill for this task question is still valid.

Thanks,
ferruh
  
Stephen Hemminger June 27, 2017, 10:26 p.m. UTC | #4
On Mon, 26 Jun 2017 10:42:13 +0100
Radu Nicolau <radu.nicolau@intel.com> wrote:

> From: Michal Jastrzebski <michalx.k.jastrzebski@intel.com>
> 
> If-MIB xstats:
> ifNumber
> ifIndex
> ifType
> ifMtu
> ifSpeed
> ifPhysAddress
> ifOperStatus
> ifLastChange
> ifHighSpeed
> ifConnectorPresent
> ifCounterDiscontinuityTime
> 
> EtherLike-MIB xstats:
> dot3PauseOperMode
> dot3StatsDuplexStatus
> dot3StatsRateControlAbility
> dot3StatsRateControlStatus
> dot3ControlFunctionsSupported
> 
> -updated in v2: coding style
> 
> Signed-off-by: Piotr Azarewicz <piotrx.t.azarewicz@intel.com>
> Signed-off-by: Michal Jastrzebski <michalx.k.jastrzebski@intel.com>
> Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>

Although this maybe the easiest way for Intel, and satisfy a specific user's
request. It is not a good way forward for the DPDK project.

This must be generic, not specific to device drivers.
If implementing a MIB variable  requires more information than ethdev API
has now, then extend ethdev API first.

One of the common things in open source projects, is that when you want
to add one new feature for one constrained portion; the maintainers require
you to implement a generic solution. This falls into that category.
  
Pattan, Reshma July 5, 2017, 1:02 p.m. UTC | #5
> -----Original Message-----

> From: Yigit, Ferruh

> Sent: Tuesday, June 27, 2017 12:36 PM

> > For 2, does the "use existing methods" include calling xstats? If so,

> > then we can just drop the requirement for 2 to have any new functions

> > implemented in the driver. Instead, have the information provided by

> > drivers in the normal xstats call, but have a new ethdev API to

> > provide that information to the app - basically hiding the xstats

> > complexity underneath.

> 

> I was thinking another dev_ops similar to xstats, but re-using xstats can be

> better idea here.

> 

> so option 2 becomes:

> [2] An eth_dev API to use existing APIs to get information from PMDs and

> wrap MIBs related xstats calls.

> 


Instead of getting information/configuration related mib attributes  in xstats_get,  we should  have new eth_dev op to get  all those mib attributes which don’t have any ethdev API. 
Then the new eth_dev API can call this new eth_dev op and other existing ethdev APIs to gather all mib information and expose that to user.

Thanks,
Reshma
  
Pattan, Reshma July 6, 2017, 11:48 a.m. UTC | #6
Hi ,

> -----Original Message-----
> From: Stephen Hemminger [mailto:stephen@networkplumber.org]
> Sent: Tuesday, June 27, 2017 11:26 PM
> To: Nicolau, Radu <radu.nicolau@intel.com>
> Cc: dev@dpdk.org; Lu, Wenzhuo <wenzhuo.lu@intel.com>; Pattan, Reshma
> <reshma.pattan@intel.com>; Jastrzebski, MichalX K
> <michalx.k.jastrzebski@intel.com>; Jain, Deepak K
> <deepak.k.jain@intel.com>; Van Haaren, Harry
> <harry.van.haaren@intel.com>; piotrx.t.azarewicz@intel.com
> Subject: Re: [dpdk-dev] [PATCH v2] drivers/net: add support for IF-MIB and
> EtherLike-MIB for e1000
> 
> On Mon, 26 Jun 2017 10:42:13 +0100
> Radu Nicolau <radu.nicolau@intel.com> wrote:
> 
> > From: Michal Jastrzebski <michalx.k.jastrzebski@intel.com>
> >
> > If-MIB xstats:
> > ifNumber
> > ifIndex
> > ifType
> > ifMtu
> > ifSpeed
> > ifPhysAddress
> > ifOperStatus
> > ifLastChange
> > ifHighSpeed
> > ifConnectorPresent
> > ifCounterDiscontinuityTime
> >
> > EtherLike-MIB xstats:
> > dot3PauseOperMode
> > dot3StatsDuplexStatus
> > dot3StatsRateControlAbility
> > dot3StatsRateControlStatus
> > dot3ControlFunctionsSupported
> >
> > -updated in v2: coding style
> >
> > Signed-off-by: Piotr Azarewicz <piotrx.t.azarewicz@intel.com>
> > Signed-off-by: Michal Jastrzebski <michalx.k.jastrzebski@intel.com>
> > Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
> 
> Although this maybe the easiest way for Intel, and satisfy a specific user's
> request. It is not a good way forward for the DPDK project.
> 
> This must be generic, not specific to device drivers.
> If implementing a MIB variable  requires more information than ethdev API
> has now, then extend ethdev API first.
> 

Yes, most of the MIB attributes can be fetched from rte_eth_dev_data/rte_eth_dev_info. 
Re expressing my opinion (a) below which I did in other mail: 
(a)For the MIB attributes which do not have any ethdev API support, how about getting all of them from PMDs via a new dev_op like xstats_get?. 
   Then add the new eth_dev API, which does call to this new dev_op and other existing ethdev APIs to gather all mib information and expose that 
   to user based on port_id. 

(Or)

(b)Should we expand rte_eth_dev_info or rte_eth_dev_data to add missing mib attributes, fetch them from PMDs using dev_infos_get() and expose to user.
   Adding new mib attributes to existing  structs might need ABI break announcements.  
   
But both cases (a) and (b) does need some PMD changes.

Please let me know what you think about the  points a and b.

Thanks,
Reshma
  
Ferruh Yigit July 19, 2017, 10:40 a.m. UTC | #7
On 6/26/2017 10:42 AM, Radu Nicolau wrote:
> From: Michal Jastrzebski <michalx.k.jastrzebski@intel.com>
> 
> If-MIB xstats:
> ifNumber
> ifIndex
> ifType
> ifMtu
> ifSpeed
> ifPhysAddress
> ifOperStatus
> ifLastChange
> ifHighSpeed
> ifConnectorPresent
> ifCounterDiscontinuityTime
> 
> EtherLike-MIB xstats:
> dot3PauseOperMode
> dot3StatsDuplexStatus
> dot3StatsRateControlAbility
> dot3StatsRateControlStatus
> dot3ControlFunctionsSupported
> 
> -updated in v2: coding style
> 
> Signed-off-by: Piotr Azarewicz <piotrx.t.azarewicz@intel.com>
> Signed-off-by: Michal Jastrzebski <michalx.k.jastrzebski@intel.com>
> Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>

This patchset won't able to make for this release. There is already a
new RFC [1] for next release.

[1]
http://dpdk.org/dev/patchwork/patch/27032/
  

Patch

diff --git a/drivers/net/e1000/e1000_ethdev.h b/drivers/net/e1000/e1000_ethdev.h
index 9266540..1fc82b4 100644
--- a/drivers/net/e1000/e1000_ethdev.h
+++ b/drivers/net/e1000/e1000_ethdev.h
@@ -275,20 +275,79 @@  struct e1000_filter_info {
 	uint32_t syn_info;
 };
 
+#define E1000_MIB_IF_TYPE_ETHERNETCSMACD	6
+
+enum {
+	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_DISABLED = 1,
+	E1000_DOT3_PAUSE_ENABLEDXMIT,
+	E1000_DOT3_PAUSE_ENABLEDRCV,
+	E1000_DOT3_PAUSE_ENABLEDXMITANDRCV
+};
+
+enum {
+	E1000_DOT3_DUPLEX_UNKNOWN = 1,
+	E1000_DOT3_DUPLEX_HALFDUPLEX,
+	E1000_DOT3_DUPLEX_FULLDUPLEX
+};
+
+enum {
+	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).
  */
 struct e1000_adapter {
-	struct e1000_hw         hw;
-	struct e1000_hw_stats   stats;
-	struct e1000_interrupt  intr;
-	struct e1000_vfta       shadow_vfta;
-	struct e1000_vf_info    *vfdata;
-	struct e1000_filter_info filter;
-	bool stopped;
-	struct rte_timecounter  systime_tc;
-	struct rte_timecounter  rx_tstamp_tc;
-	struct rte_timecounter  tx_tstamp_tc;
+	struct e1000_hw			hw;
+	struct e1000_hw_stats		stats;
+	struct e1000_interrupt		intr;
+	struct e1000_vfta		shadow_vfta;
+	struct e1000_vf_info		*vfdata;
+	struct e1000_filter_info	filter;
+	bool				stopped;
+	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 a0da9d5..1f6fcdb 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -549,6 +549,45 @@  static const struct rte_igb_xstats_name_off rte_igbvf_stats_strings[] = {
 #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.
@@ -925,6 +964,11 @@  eth_igb_dev_init(struct rte_eth_dev *eth_dev)
 		     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);
@@ -1114,6 +1158,11 @@  eth_igbvf_dev_init(struct rte_eth_dev *eth_dev)
 		     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);
@@ -1858,12 +1907,17 @@  eth_igb_stats_reset(struct rte_eth_dev *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
@@ -1871,31 +1925,138 @@  eth_igb_xstats_reset(struct rte_eth_dev *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,
@@ -1940,27 +2101,53 @@  eth_igb_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
 	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
@@ -2050,19 +2237,46 @@  igbvf_read_stats_registers(struct e1000_hw *hw, struct e1000_vf_stats *hw_stats)
 	    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
@@ -2072,23 +2286,49 @@  eth_igbvf_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
 	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
@@ -2114,6 +2354,8 @@  eth_igbvf_stats_reset(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);
@@ -2121,6 +2363,9 @@  eth_igbvf_stats_reset(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
@@ -2366,6 +2611,8 @@  eth_igb_link_update(struct rte_eth_dev *dev, int wait_to_complete)
 {
 	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;
 
@@ -2434,6 +2681,7 @@  eth_igb_link_update(struct rte_eth_dev *dev, int wait_to_complete)
 		return -1;
 
 	/* changed */
+	adapter->if_last_change = rte_rdtsc() - adapter->sys_up_time_start;
 	return 0;
 }