版权所有,转载请注明出处http://forever.blog.chinaunix.net.
最近有开发人员反映dstat输出的网卡信息,存在连续几秒(多的达到20秒)带宽为零的情况,但是开发人员反馈可以在目标机器上抓取到发送出去的数据包。
1. dstat带宽输出为0的原因?
分析dstat的源码,dstat通过读取/proc/net/dev的数据来计算网络带宽。那么带宽为0,说明/proc/net/dev数据没有更新。
2. /proc/net/dev数据更新不及时的原因?
分析kernel代码,/proc/net/dev数据的更新通过调用驱动中的ndo_get_stats64()方法获取网卡的统计信息。
3. 网卡统计信息更新不及时的原因?
David S.Miller的解释:
It's a tradeoff between excess DMA traffic updating the statistics,
and having them updated more frequently.
Actually, the thing that matters is when ->get_stats() is called.
So if a driver can trigger a statistics DMA update at ->get_stats()
time, that's probably what it should do. But this could get
expensive and make the "do DMA less often" optimization less useful.
也就是说网卡统计信息,考虑到不能过度的频繁更新DMA数据。
4. 以Intel网卡igb驱动为例,每两秒更新一次,或者通过ethtool命令强制更新。
Previously, igb stats were updated :
- By watchdog timer, every 2 secs
- Every time an "ethtool -S ethX" was done
There is no general guarantee netdev stats are immediately available to
user.
ndo_get_stats() is not allowed to sleep, (because of bonding...), so
drivers can not always provide accurate stats, if they need to make a
long transaction with hardware.
Other drivers do the same (provide hardware statistics), with about one
second resolution.
So the "resulted in false observations from userspace." is something
that might upset admins, but is not a hard requirement of netdev stats.
5. 为了解决这个问题,引入了在读取时更新的机制,该机制只是增加了增加了准确性,但仍然不能保证绝对实时。
This patch also increase the accuracy of stats in /proc/net/dev, by
updating the adapter stats when reading /proc/net/dev. Previously
the stats were only updated by the watchdog timer every 2 sec, which
resulted in false observations from userspace.
-
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
-
index 55edcb7..6cec297 100644
-
--- a/drivers/net/igb/igb_main.c
-
+++ b/drivers/net/igb/igb_main.c
-
@@ -4218,11 +4218,17 @@ static void igb_reset_task(struct work_struct *work)
-
* @netdev: network interface device structure
-
*
-
* Returns the address of the device statistics structure.
-
- * The statistics are actually updated from the timer callback.
-
+ * The statistics are also updated from the timer callback
-
+ * igb_watchdog_task().
-
**/
-
static struct net_device_stats *igb_get_stats(struct net_device *netdev)
-
{
-
- /* only return the current stats */
-
+ struct igb_adapter *adapter = netdev_priv(netdev);
-
+
-
+ /* update stats */
-
+ igb_update_stats(adapter);
-
+
-
+ /* return the current stats */
-
return &netdev->stats;
-
}
-
-
@@ -4307,7 +4313,7 @@ static int igb_change_mtu(struct net_device *netdev, int new_mtu)
-
-
void igb_update_stats(struct igb_adapter *adapter)
-
{
-
- struct net_device_stats *net_stats = igb_get_stats(adapter->netdev);
-
+ struct net_device_stats *net_stats = &adapter->netdev->stats;
-
struct e1000_hw *hw = &adapter->hw;
-
struct pci_dev *pdev = adapter->pdev;
-
u32 reg, mpc;
阅读(9261) | 评论(0) | 转发(0) |