目的
测试并优化Linux内核发包
环境
ga-b250m-d3h I7-7700k, 4核8线程,no_trubo=1即最高4.2GHz X520-T1 ubuntu 18.04, linux-image-4.15.0-XX
netmap
netmap是一种网卡旁路方法,用netmap测试,发包在 14.3Mpps, 单cpu 60%。测试命令
1
|
|
Linux多线程发包
在模块中用kthread创建多线程,每个线程构造skb,然后调dev_queue_xmit(skb)。测试发现cpu全部100%,发包大多在12Mpps
1 2 3 4 |
|
猜测可能优化点
- qdisc流控
- skb的申请、释放
优化qdisc流控
qdisc流控可以简单看作把包存下,然后再发送出去。取消qdisc应该能减少一层消耗。
1
|
|
将上面的代码copy到模块,就跳过了qdisc。其实noqueue也是这个流程,但为什么noqueue的pps、cpu都没提升呢?
测试发现skb->xmit_more是关键,ixgbe中关于xmit_more的代码:
1 2 3 4 5 6 7 8 |
|
noqueue中没有设置xmit_more,但fq_codel,pfifo_fast等用到qdisc框架的都会设置xmit_more,qdisc是用skb->next将skb串起来,当skb->next != NULL时在dev_hard_start_xmit就会设置xmit_more=1。
照此优化,在我们的模块中每次申请多个包,将他们用skb->next串起来再发送。优化后发包在14.2Mpps,每个cpu都60%。
优化skb的申请、释放
每秒申请、释放14M的skb有点多。。。
我们可以创建percpu的skb池,申请的时候从池子里拿,释放的时候放回池子。
- 怎么做到释放时放回池子?用skb->destructor指向我们的回调函数即可
- 怎么做到不让Linux内核释放skb以及skb->data的空间?增加如下patch重新编译内核,设置skb池子里的skb->fclone = SKB_FCLONE_USER即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
|
优化后: 单独优化skb申请释放: 发送14.2Mpps 每个cpu 50%
qdisc优化和skb申请释放优化: 发送14.2Mpps 每个cpu 20%
只用1个cpu:发送9.6Mpps, cpu 100% 用2个cpu:发送14.2Mpps, 每个cpu 80%
相比netmap单cpu 60%发送14.3Mpps, 两轮优化后还略差些,不过perf看热点已经在ixgbe里了