Linux内核可以选择启用TCP接收副本卸载功能(CONFIG_NET_DMA
)。我使用iperf
(TCP窗口大小= 250 KB,缓冲区长度= 2 MB)和oprofile来测试三种情况下的性能:使用和不使用NET_DMA,NET_DMA启用和sk_rcvlowat
设置为200 KB 。结果如下:
禁用NET_DMA:带宽可达930 Mbps,__copy_tofrom_user
占用cpu时间的36.1%。
启用NET_DMA:带宽小于上述情况40 Mbps(890 Mbps),__copy_tofrom_user
消耗33.5%的CPU时间。
启用NET_DMA(sk_rcvlowat = 200KB):带宽为874 Mbps,__copy_tofrom_user
占用cpu时间的25.1%。
我还尝试检查函数tcp_recvmsg()(在/net/ipv4/tcp.c中)(内核版本是2.6.32.2)。这是我理解NET_DMA工作方式的方式:
//在tcp_revmsg()
的开头target = sock_rcvlowat(sk, flags & MSG_WAITALL, len);
#ifdef CONFIG_NET_DMA
tp->ucopy.dma_chan = NULL; preempt_disable(); skb = skb_peek_tail(&sk->sk_receive_queue); { int available = 0; if (skb) available = TCP_SKB_CB(skb)->seq + skb->len - (*seq); if ((available < target) && (len > sysctl_tcp_dma_copybreak) && !(flags & MSG_PEEK) && !sysctl_tcp_low_latency && dma_find_channel(DMA_MEMCPY)) { preempt_enable_no_resched(); tp->ucopy.pinned_list = dma_pin_iovec_pages(msg->msg_iov, len); } else { preempt_enable_no_resched(); } }
#ENDIF
len
:是缓冲区长度,可以使用-l
iperf
选项指定
target
:是应返回的最小字节数tcp_recvmsg()
。如果未设置sk->sk_rcvlowat
,我看到该目标通常得到值1(在target
= 1的情况下很少发生DMA传输。)
available
:来自接收队列的第一个skb
可用的字节数。
我认为条件(目标&lt; available)对于确定tcp_recvmsg()
是否应该使用DMA至关重要。当我从I / OAT补丁文件中的注释中读取时,如果存在上下文切换使进程进入休眠状态并等待更多数据,则此条件为真。
//在tcp_recvmsg()
的while循环中if(复制&gt; =目标){
/* Do not sleep, just process backlog. */ release_sock(sk); lock_sock(sk);
}其他
sk_wait_data(sk, &timeo);
当进程处于休眠状态时,到达的数据包将在tcp_dma_try_early_copy()
tcp_rcv_established()
中/net/ipv4/tcp_input.c
直接发送到用户空间缓冲区。也许这是NET_DMA的有效点,进程进入休眠状态,但数据可以通过硬件移动到其缓冲区。
//在/net/ipv4/tcp_input.c:tcp_dma_try_early_copy()
if((tp-> ucopy.len == 0)||
(tcp_flag_word(tcp_hdr(skb)) & TCP_FLAG_PSH) || (atomic_read(&sk->sk_rmem_alloc) > (sk->sk_rcvbuf >> 1))) { tp->ucopy.wakeup = 1; sk->sk_data_ready(sk, 0);
}
tcp_dma_try_early_copy()
中的DMA处理将停止其作业,并在没有更多缓冲区(tp->ucopy.len == 0
)或分配的skb
的总大小大于1时唤醒休眠进程/ 2 sk_rcvbuf
(我发现sk_rcvbuf
设置为TCP窗口大小iperf
)。
这是我第一次使用Linux中的TCP / IP堆栈。我不确定上面的结论是否正确,如果我错了请修理我。我的问题是:
Q1:为什么NET_DMA启用情况下的带宽总是低于没有NET_DMA的情况?
Q2:是否有一组很好的值(TCP窗口大小,缓冲区长度,sk_rcvlowat
)来提升NET_DMA启用情况下的性能?
问题3:每次DMA传输仅约1448字节。它是否太小而不能被DMA化?
任何建议都表示赞赏。提前谢谢。
答案 0 :(得分:2)
我的猜测是,对于小数据包(现在认为1448很小),激活和等待IOAT中断的延迟开销高于简单复制内存的开销,特别是当内存和CPU访问速度很快时。现代服务器可以使用memcpy
推送5GB /秒。
对于10Gbit / sec以太网情况,尽可能使用更高的MTU并且肯定更大的缓冲区大小是值得的。我认为接收卸载的原始测试仅在单个数据包大约为PAGE_SIZE时开始显示性能提升。