/proc/net/dev 提供有关传输字节的错误信息

/proc/net/dev 提供有关传输字节的错误信息

我有一台 Linux 内核 4.1.25 的中兴路由器,我在其上安装了 snmp 代理(mini-snmpd)来控制流量。

由于我得到的数据不准确,我进行了一些调查,发现 ifconfig 和 /proc/net/dev 都给出了错误的数据,而 zte 程序 (cspd/httpd) 提供了正确的值。

ifconfig 返回 eth4 的信息,这是我插入的接口:

RX 字节:177365531 (161.1 MiB) TX 字节:12507777123 (11.6Gib)

路由器网页显示了该接口的更大且我相信正确的值:

接收/发送的字节数 100655800471/286284079917

如果我做一个速度测试-cli从我的计算机上,我可以看到网络计数器根据已传输的传输数据 speedtest-cli 报告(2/3GB 输入/输出)而增加。然而ifconfig几乎不动,有时增加+300MB,有时+100MB。


   Speedtest by Ookla

     Server: xxxxxx (id = 14979)
        ISP: xxxxxx
    Latency:     1.93 ms   (0.12 ms jitter)
   Download:  2339.50 Mbps (data used: 2.9 GB )
     Upload:  2339.21 Mbps (data used: 2.1 GB )
Packet Loss:     0.0%

是否有原因导致内核没有获得准确的数据,而中兴通讯的程序却获得了准确的数据?

编辑:

好吧,我相信我已经找到了原因,而不是解决方案(如果有的话)。

有一些可调参数/proc/中兴通讯/sys/ffe

如果我做: echo npu 0 > /proc/zte/sys/ffe/cmd

我开始看到良好的网络图表,但传入流量似乎限制在 1.7Gbps 左右(我之前获得了约 2.35Gbps)

如果我做: echo ffe 0 > /proc/zte/sys/ffe/cmd

下载和上传速度急剧下降至 300mbps 左右。

我一直在研究npu和ffe代表什么,它们似乎是一些硬件网络加速器(网络处理单元和快进引擎)。

我仍然不知道为什么 /proc/net/dev 没有注意到通过 npu 的总流量,但是用户空间中的程序却注意到了,以及是否可以以某种方式解决这个问题。有一些 no_delete、timer、flowctrl 选项,我将用它们来玩一下,看看它是否能够更新 net/dev 文件。

编辑2:

好吧,经过更多研究后,我在 cspd 进程上使用了 strace,并通过在路由器网络上请求 eth 统计信息,我可以看到一个 write() ,看起来像是对 cspd 进程函数 CmEthGetPortBasicStats() 的调用。使用 ghidra 查看 cspd 二进制文件,我发现文件 /dev/switch_dev 中有一个 fopen(),后跟一个 ioctl,当它要求基本统计数据时,其值为 0x38 (56),以及用于不同事物(例如设置速度)的其他值,双工、接口开/关...我尝试创建一个 ioctl 程序来从 switch_dev 检索数据。还没有成功,只收到几个字节。

编辑3:

好的,所以 cspd 二进制文件有两个功能:

https://i.stack.imgur.com/4OltN.png

这个函数完全符合我的要求,它立即接收所有接口的统计信息。当我从路由器网页检查 eth 统计信息时,会调用此函数。

https://i.stack.imgur.com/gfl1x.png

这个函数的作用相同,但它针对每个接口执行,我注意到当我在控制台中运行此命令时会调用它: sendcmd 1 switch_mgr getPortStats [iface 编号]

发送命令

因此,尽管还无法直接与 /dev/switch_mgr 交互,但我已经修补了 mini-snmpd 源代码,以生成一个假的 /proc/net/dev,其中添加了来自 sendcmd 命令的数据,mini-snmpd 解析该命令而不是原来最终实现了我一直在寻找的东西:

格拉法纳1

我知道该解决方案并不完美,因为我将 ioctl() 调用更改为 5 popen("sendcmd 1 switch_mgr...") 但我并没有真正看到因此造成的任何明显的开销,并且它为 mini-snmpd 提供了正确的数字。显然这并不能修复 ifconfig 因为我创建了一个假的/proc/net/dev/var/tmp/dev-fake, ifconfig 不会从中获取信息。也许我稍后会编译一个新的静态 ifconfig,但这对我来说不是优先事项。

对我来说这已经足够了,但如果有人想帮助我直接与/dev/switch_dev

相关内容