我有一台 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 解析该命令而不是原来最终实现了我一直在寻找的东西:
我知道该解决方案并不完美,因为我将 ioctl() 调用更改为 5 popen("sendcmd 1 switch_mgr...") 但我并没有真正看到因此造成的任何明显的开销,并且它为 mini-snmpd 提供了正确的数字。显然这并不能修复 ifconfig 因为我创建了一个假的/proc/net/dev在/var/tmp/dev-fake, ifconfig 不会从中获取信息。也许我稍后会编译一个新的静态 ifconfig,但这对我来说不是优先事项。
对我来说这已经足够了,但如果有人想帮助我直接与/dev/switch_dev