最近半年接触的项目大多是高端5G平台,很多都搭载了pcie网卡,网卡性能优化一直是一个比较烦人的点,反复测测测真的很烦人,又没有什么改善。所以这里把我最近做的项目遇到的问题和解决方案记录一下,算是做个总结,也希望能给大家带来帮助,节省一些开发时间。

更换测试机

我所接触到的项目上,一般是百兆、千兆或者2.5G网卡,百兆的是在车机项目上,上面若干个port口有百兆有千兆的,百兆的一般没什么问题,毕竟传输速率也不高。如果有问题,可以尝试更换对端设备。一般测试都是跟PC打流,我也遇到过同一台设备跟一台PC打流数据惨不忍睹,TCP/UDP速率和丢包率都差,然后换了台PC对打,竟然都到95Mbps,也没有丢包。千兆的也一样,如果有Ubuntu系统电脑测试更好,因为Ubuntu系统测下来感觉更稳定性能更好些,同样的网卡插到windows系统PC上出来数据差很多。

总之,调网卡不要怕测,不测怎么出数据怎么发现问题。

最快提升方案——绑定大核

这种方案基本算是现成方案,一般能解决大部分速率问题。

比较新的平台一般都是采用了4小核3中核1大核这种CPU架构,大核频率最高,当然性能也最高了。但是通常它都是闲着的,因为系统里存在着一个irq_balance服务,你可以把他理解成个派活的,给系统里这些中断分配给各个核心去运行,一般活是分不到大核那边的。但是通过测试发现,UDP丢包主要都是在rx端,也就是在接收时候丢掉了。引用原厂技术的话“关掉留空,tx端按照设定带宽法爆,rx端收包数量不足,此时可以看到网卡寄存器显示有大量的rx_missed统计(即rx_fifo满了,无法再接收了)。网卡硬件收不下,是因为rx封包处理不及时,没有更多的fifo可以用来接收封包。”大概意思就是CPU这边数据处理不过来,而另一边又一直在发, 数据就这样丢掉了。

那么要让CPU处理数据效率高,肯定要用性能最好的大核了,根据高通的建议把网卡的中断绑定在大核上,速率果然改善了很多。以下是绑定方案:

<1>set core control feature
/sys/devices/system/cpu/cpu7/core_ctl # echo 1 > min_cpus
/sys/devices/system/cpu/cpu7/core_ctl # echo 1 > max_cpus

<2>disable irq balance by following way
device/qcom/common/rootdir/etc/init.qcom.rc

service msm_irqbalance /system/bin/msm_irqbalance -f /system/vendor/etc/msm_irqbalance.conf
class core
user root
group root
disabled

<3> echo 80 > /proc/irq/<your RX interrupt num>/smp_affinity

执行这几步就可以了,其中第二步关闭irq_balance 服务,因为有些客户不想关闭,可以用函数替代单独关闭网卡的中断平衡,相关函数定义直接在代码里搜就行。

irq_modify_status(irq, 0, IRQ_NO_BALANCING);

相关修改方案放在这里,大家可以参考下,驱动部分修改不同型号网卡基本都可以用,原理都一样。

--- a/kernel/msm-4.19/drivers/net/ethernet/rtl8125/r8125_n.c
+++ b/kernel/msm-4.19/drivers/net/ethernet/rtl8125/r8125_n.c
@@ -38,6 +38,7 @@
 #include <linux/string.h>
 
 #include <linux/module.h>
+#include <linux/device.h>
 #include <linux/version.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
@@ -97,7 +98,7 @@
 /* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
    The RTL chips use a 64 element hash table based on the Ethernet CRC. */
 static const int multicast_filter_limit = 32;
-
+static int mac_test_irq = 0;
 #define _R(NAME,MAC,RCR,MASK, JumFrameSz) \
     { .name = NAME, .mcfg = MAC, .RCR_Cfg = RCR, .RxConfigMask = MASK, .jumbo_frame_sz = JumFrameSz }
 
@@ -11181,6 +11182,20 @@ static void rtl8125_init_napi(struct rtl8125_private *tp)
         }
 }
 
+
+static ssize_t mac_irq_show(struct device *dev, struct device_attribute *attr,
+               char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%d\n",mac_test_irq);
+}
+static ssize_t mac_irq_store(struct device *dev, struct device_attribute *attr,
+               const char *buf, size_t count)
+{
+       return count;
+}
+static DEVICE_ATTR_RW(mac_irq);
+
 static int __devinit
 rtl8125_init_one(struct pci_dev *pdev,
                  const struct pci_device_id *ent)
@@ -11333,7 +11348,7 @@ rtl8125_init_one(struct pci_dev *pdev,
         device_set_wakeup_enable(&pdev->dev, tp->wol_enabled);
 
         netif_carrier_off(dev);
-
+device_create_file(&pdev->dev, &dev_attr_mac_irq);
         printk("%s", GPL_CLAIM);
 
 out:
@@ -11613,7 +11628,7 @@ static int rtl8125_open(struct net_device *dev)
                 goto err_free_all_allocated_mem;
 
         if (netif_msg_probe(tp)) {
-                printk(KERN_INFO "%s: 0x%lx, "
+                printk(KERN_INFO "debug>>>%s: 0x%lx, "
                        "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
                        "IRQ %d\n",
                        dev->name,
@@ -11622,6 +11637,7 @@ static int rtl8125_open(struct net_device *dev)
                        dev->dev_addr[2], dev->dev_addr[3],
                        dev->dev_addr[4], dev->dev_addr[5], dev->irq);
         }
+ mac_test_irq = dev->irq;
+ irq_modify_status(dev->irq,0,IRQ_NO_BALANCING);
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
         INIT_WORK(&tp->task, NULL, dev);
--

创建个节点把网卡中断号存进去,然后在开机时候自动执行下绑核操作,可以在.sh文件里加,如果不生效可以自己写个脚本,然后在.rc文件里加个service调用就行了,具体怎么做看平台了,这里就不展示了。

其它手段

有些时候绑定大核之后速率还是不达标怎么办?我知道你很急但你先别急。

确定真实速率

一般打流测试都是用的iperf,这个确实方便,但是本身也是有问题的,尤其是网卡速率高了以后,问题更明显。这个apk自己统计的时候就不全,就我自己调试2.5G网卡的时候,都绑定大核了,打流还是显示只有1.7Gbps左右,搞毛啊。然后高通让我抓个tcpdump看看,一看实际速率都有2.2Gbps了,这不坑人呢么,所以有时候也不要只看apk显示的数据,可以自己抓个tcpdump看下。方法也很简答

adb root
adb shell
tcpdump udp -i eth0 port 5001 -w data/soc-server.pcap

-i:网卡名称

port:打流端口,可以自己设置,也可以默认的都行

-w:保存tcpdump文件,我这里是保存为pcap文件方便等下用工具解析

执行完之后再开个串口打流,打流完ctrl +C,把tcpdump从设备pull出来,




windows wireshark 丢包_linux


然后用wireshark打开,点击截图中选项


windows wireshark 丢包_Powered by 金山文档_02


修改下默认配置


windows wireshark 丢包_ci_03


这里10^9Bits/s就约等于1Gbps。

尝试不同参数

iperf2 -s -u -i 1 -p 5001 -g 8000 -w 8M

iperf2 -c 192.168.195.2 -u -i 1 -b 1000M -p 5001 -g 8000 -w 8M -t 30

可以调整-g 为4000,-w为4M,组合尝试,但注意收发两端设置大小要一致

编译user版本

如果办法都尝试了还是不行,就编译一个开启root、adb等权限的user版本来测试下。按实测情况来看user版本表现确实好,如果userdebug版本不行的话就编个user版本来试下吧,大概率就可以了。

小结

以上是网卡速率优化过程中的一些经验总结,优化过程是一个比较慢有点烦人的过程,希望这些能帮到你,缩短一些调试时间~