您好Stackoverflow专家
我无法在多个内核中应用ip分段。
我的最终问题是,是否可以为每个不同的直接池和间接池分配多个ip分片表。
如果有人能指出我在这里做错了什么,或者提供一些替代解决方案,我真的很感激。
目的
我正在尝试在多个内核中应用ip分段,并通过大于MTU的消息来最大化吞吐量性能。
问题
如果我尝试将碎片表分配给每个内核,则会出现分段错误,并且无论我缩小碎片表的大小如何,都会发生这种情况。 我尝试分配池和碎片表的方式如下所示。
for each coreid, coreid < allocated cores; coreid++
fragmentation_table[coreid] = rte_ip_frag_table_create(...);
direct_pool[coreid] = rte_pktmbuf_pool_create(...);
indirect_pool[coreid] rte_pktmbuf_pool_create(...);
因此,或者,我为每个lcores分配了多个碎片表,但让直接池和间接池共享在一起。
for each coreid, coreid < allocated cores; coreid++
fragmentation_table[coreid] = rte_ip_frag_table_create(...);
direct_pool = rte_pktmbuf_pool_create(...);
indirect_pool = rte_pktmbuf_pool_create(...);
情况
现在,当我使用多个内核从本地主机向远程主机发送消息时,远程主机仅在我发送消息时成功添加了消息,并添加了一个延迟,例如(为每个发送消息添加sleep(1);)。能够接收从本地到远程的消息。但是,当我尝试毫无延迟地发送数据时,无法接收任何数据。
结论
我个人认为应该为每个逻辑核心分配直接池和间接池,我认为这是主要问题。由于只能使用一个逻辑内核才能成功使用碎片表,因此我怀疑我没有在多个内核中正确使用碎片表。
我真的很想从DPDK专家那里得知我所面临的这个问题,并且非常感谢您对此提供的任何建议...
static int
setup_queue_tbl(struct lcore_rx_queue *rxq, uint32_t lcore, uint32_t queue)
{
int socket;
uint32_t nb_mbuf;
uint64_t frag_cycles;
char buf[RTE_MEMPOOL_NAMESIZE];
socket = rte_lcore_to_socket_id(lcore);
if (socket == SOCKET_ID_ANY)
socket = 0;
frag_cycles = (rte_get_tsc_hz() + MS_PER_S - 1) / MS_PER_S * max_flow_ttl;
if ((rxq->frag_tbl = rte_ip_frag_table_create(max_flow_num,
IP_FRAG_TBL_BUCKET_ENTRIES, max_flow_num, frag_cycles,
socket)) == NULL) {
printf("rte_ip_frag_table_create failed!!!!\n");
return -1;
}
nb_mbuf = RTE_MAX(max_flow_num, 2UL * MAX_PKT_BURST) * MAX_FRAG_NUM;
nb_mbuf *= (port_conf.rxmode.max_rx_pkt_len + BUF_SIZE - 1) / BUF_SIZE;
nb_mbuf *= 1;
nb_mbuf += nb_rxd + nb_txd;
if (transfer_pool[lcore] == NULL) {
snprintf(buf, sizeof(buf), "pool_recieve_%d", socket);
receive_pool[lcore] = rte_pktmbuf_pool_create(buf, nb_mbuf, MEMPOOL_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, socket);
snprintf(buf, sizeof(buf), "pool_transfer_%d", socket);
transfer_pool[lcore] = rte_pktmbuf_pool_create(buf, nb_mbuf, MEMPOOL_CACHE_SIZE, 0, PKT_SIZE + 128, socket);
snprintf(buf, sizeof(buf), "pool_direct_%d", socket);
direct_pool[lcore] = rte_pktmbuf_pool_create(buf, nb_mbuf, MEMPOOL_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, socket);
snprintf(buf, sizeof(buf), "pool_indirect_%d", socket);
indirect_pool[lcore] = rte_pktmbuf_pool_create(buf, nb_mbuf, MEMPOOL_CACHE_SIZE, 0, 0, socket);
}
snprintf(buf, sizeof(buf), "mbuf_rx_ring_%d", lcore);
rx_ring[lcore] = rte_ring_create(buf, 512, socket, 0);
snprintf(buf, sizeof(buf), "mbuf_tx_ring_%d", lcore);
tx_ring[lcore] = rte_ring_create(buf, 512, socket, 0);
// for packet assemble
rxq->ar = (struct assembled_result *)malloc(sizeof(struct assembled_result));
rxq->ar->length = 0;
rxq->ar->assembled_pkt = (char *)malloc(sizeof(char)*PKT_SIZE);
return 0;
}
这是完整的源代码,我要确保它正确的代码在dpdk_init.h
中。https://github.com/SungHoHong2/DPDK-Experiment/blob/master/dpdk-server-multi/dpdk_init.h
答案 0 :(得分:1)
这将帮助您获得答案,而不是猜测;)
DPDK程序员指南明确指出:
片段表上的所有更新/查找操作都不是线程安全的。
因此,每个lcore必须具有其自己的片段表或必须使用锁。
默认情况下,除非我们传递MEMPOOL_F_SP_PUT
之类的标志,否则DPDK中的默认内存池是线程安全的。因此,回答您的问题:
是否可以为每个不同的直接池和间接池分配多个ip分段表。
默认情况下,很少有lcore可以共享内存池。
由于没有源代码,所以我想根本原因是片段的TTL不到1秒,因此sleep(1)
包到达太晚而无法重新组装。
重新组装非常耗时又占空间,应不惜一切代价避免。
考虑通过更改协议或使用巨型帧将消息放入一个数据包的一些方法。
答案 1 :(得分:0)
答案是一个非常基本的答案。 问题在于大页面的配置。 对于我未测试的每个群集,巨大的页面大小是不同的。
一个正在分配碎片表的集群是...
AnonHugePages: 208896 kB
HugePages_Total: 8
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 1048576 kB
当我尝试分配碎片表时,另一个一直返回分段错误的集群是...
AnonHugePages: 6144 kB
HugePages_Total: 1024
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
这是每个逻辑核心扩展rx和tx -queue的基本性能,如您所见,可以使用多个rx-tx队列,每个队列与带有逻辑核心和所需池的frag-table相关联。