我有一个奇怪的掉落问题,要理解我的问题,最好的方法是看一下这个简单的代码段:
while( 1 )
{
if( config->running == false ) {
break;
}
num_of_pkt = rte_eth_rx_burst( config->port_id,
config->queue_idx,
buffers,
MAX_BURST_DEQ_SIZE);
if( unlikely( num_of_pkt == MAX_BURST_DEQ_SIZE ) ) {
rx_ring_full = true; //probably not the best name
}
if( likely( num_of_pkt > 0 ) )
{
pk_captured += num_of_pkt;
num_of_enq_pkt = rte_ring_sp_enqueue_bulk(config->incoming_pkts_ring,
(void*)buffers,
num_of_pkt,
&rx_ring_free_space);
//if num_of_enq_pkt == 0 free the mbufs..
}
}
此循环正在从设备中检索数据包,并将其推入队列以供另一个lcore进一步处理。
当我用Mellanox卡运行测试时,以2.5M p / s发送20M(20878300)数据包时,循环似乎丢失了一些数据包,而pk_captured始终类似于19M或类似数据。
rx_ring_full永远不会为真,这意味着num_of_pkt总是
现在,如果从该片段中删除了rte_ring_sp_enqueue_bulk调用(并确保释放所有的mbuf),则pk_captured始终等于我发送至NIC的数据包数量。
因此,似乎(但我无法解决这个想法)rte_ring_sp_enqueue_bulk有点太慢,并且在一次调用rte_eth_rx_burst与另一次调用之间,由于NIC上的满环而导致丢包,但是,为什么num_of_pkt(来自rte_eth_rx_burst)总是小于好像总是有足够的空间容纳MAX_BURST_DEQ_SIZE(小得多)?
请注意,MAX_BURST_DEQ_SIZE为512。
编辑1:
也许这些信息可能会有所帮助:丢弃似乎也可以通过rte_eth_stats_get看到,或更准确地说,没有丢弃被报告(忽略且错误数为0),但是ipackets的值等于我的计数器pk_captured(丢失的数据包刚刚消失了吗? ?)
编辑2:
根据ethtools,rx_crc_errors_phy为零,并且所有数据包都在PHY级别接收(rx_packets_phy用正确数量的已传输数据包更新)。
来自rte_eth_stats的rx_nombuf的值似乎包含废纸((这是来自我们测试应用程序的打印内容):
OUT(4):端口1统计信息:ipkt:19439285,opkt:0,ierr:0,oerr:0,imiss:0,rxnobuf:2061021195718
对于2000万个数据包的传输,您可以看到rxnobuf是垃圾,或者它具有我不理解的含义。日志由以下人员生成:
log("Port %"PRIu8" stats: ipkt:%"PRIu64",opkt:%"PRIu64",ierr:%"PRIu64",oerr:%"PRIu64",imiss:%"PRIu64", rxnobuf:%"PRIu64,
config->port_id,
stats.ipackets, stats.opackets,
stats.ierrors, stats.oerrors,
stats.imissed, stats.rx_nombuf);
统计信息来自rte_eth_stats_get。
数据包不是即时生成的,而是从现有的PCAP重放的。
编辑3
在回答了Adriy的问题(谢谢!)之后,我包括了Mellanox卡的xstats输出,同时使用较小的数据包集再现了相同的问题,我可以看到rx_mbuf_allocation_errors得到了更新,但似乎包含垃圾:
OUT(4): rx_good_packets = 8094164
OUT(4): tx_good_packets = 0
OUT(4): rx_good_bytes = 4211543077
OUT(4): tx_good_bytes = 0
OUT(4): rx_missed_errors = 0
OUT(4): rx_errors = 0
OUT(4): tx_errors = 0
OUT(4): rx_mbuf_allocation_errors = 146536495542
这些计数器似乎也很有趣:
OUT(4): tx_errors_phy = 0
OUT(4): rx_out_of_buffer = 257156
OUT(4): tx_packets_phy = 9373
OUT(4): rx_packets_phy = 8351320
其中rx_packets_phy是我一直发送的确切数据包数量,然后将rx_out_of_buffer与rx_good_packets求和就得出了确切的数量。因此,似乎mbuf耗尽了,一些数据包被丢弃了。
我对原始代码进行了调整,现在使用link从RX环上复制了mbuf,它们立即释放了内存,另一个lcore对该副本进行了进一步的处理。但这并不能解决问题,事实证明,要解决该问题,我必须禁用数据包处理并释放数据包副本(在另一个lcore上),这没有任何意义。
好吧,将做更多的调查,但是至少rx_mbuf_allocation_errors似乎需要在这里修复。
最佳答案
我猜想,调试rx_nombuf
计数器是一种方法。它可能看起来像是垃圾,但是实际上,此计数器不反映丢弃的数据包的数量(像ierrors
或imissed
一样),而是反映失败的RX尝试次数。
这是MLX5 PMD的片段:
uint16_t
mlx5_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n)
{
[...]
while (pkts_n) {
[...]
rep = rte_mbuf_raw_alloc(rxq->mp);
if (unlikely(rep == NULL)) {
++rxq->stats.rx_nombuf;
if (!pkt) {
/*
* no buffers before we even started,
* bail out silently.
*/
break;
因此,该问题的可能情况如下:
num_of_pkt = rte_eth_rx_burst(...)
rte_eth_rx_burst()
时,rx_nombuf
计数器都会增加。 也请看看
rte_eth_xstats_get()
。对于MLX5 PMD,有一个硬件rx_out_of_buffer
计数器,它可以证实这一理论。关于network-programming - 即使rte_eth_rx_burst没有返回完整的突发,丢弃的数据包,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49474567/