在 DPDK 的多个内核中应用 ip 分段的正确方法
Proper way to apply ip fragmentation in multiple cores in DPDK
您好 Whosebug 专家,
我无法在多核中应用 ip 分段。
我的最终问题是是否可以为每个不同的直接和间接池分配多个 ip 碎片 table。
如果有人能指出我在这里做错了什么或为我提供一些替代解决方案,我将非常感激。
目的
我正在尝试在多核中应用 ip 分段,并通过大于 MTU 的消息最大化吞吐量性能。
- 对于每个本地和远程主机(使用 1 到 8 个逻辑核心)
- 1 ~ 4 用于传输碎片消息
- 4 ~ 8 用于接收和 assemble 消息
- 正在从本地发送 4KB 消息
- 远程将消息回传给本地。
- 计算总吞吐量
问题
如果我尝试将碎片 table 分配给每个内核,则会出现分段错误,无论我缩小碎片 table 的大小都会发生这种情况。
我尝试分配池和 frag-table 的方式如下所示。
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 分配了多个碎片 table,但让直接和间接池一起共享。
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(...);
情况
现在,当我使用多个内核从本地向远程主机发送消息时,远程主机只有在我发送消息时才成功接收到消息,并添加延迟,例如(添加睡眠(1);对于每条消息发送。)我能够从本地接收消息到远程。但是,当我尝试立即发送数据时,无法接收到任何数据。
结论
就个人而言,我怀疑我应该为每个逻辑核心分配直接池和间接池,我认为这是主要问题。由于我只能使用一个逻辑核心成功使用 frag-table,我怀疑我没有在多个核心中正确使用碎片 table。
我真的很想听听 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
1。请提供源代码
这将帮助您得到答案,而不是猜测 ;)
2。片段 Table 与 lcores
DPDK程序员指南明确指出:
all update/lookup operations on Fragment Table are not thread safe.
因此每个 lcore 必须有自己的片段 table 否则必须使用锁。
3。内存池与 lcores
默认情况下,DPDK 中的内存池是线程安全的,除非我们传递像 MEMPOOL_F_SP_PUT
这样的标志。所以,回答你的问题:
whether it is possible to have multiple ip fragmentation table allocated with each different direct and indirect pool.
默认情况下,很少有 lcores 可以共享内存池。
4。猜猜!
由于没有源代码,所以我猜根本原因是片段的 TTL 小于 1 秒,所以 sleep(1)
数据包到达太晚无法重新组装。
5。旁注
重新组装是非常耗时且 space 的操作,应不惜一切代价避免。
考虑一些方法,通过更改协议或使用巨型帧将您的消息装入一个数据包。
答案是一个非常基本的答案..
问题出在大页面的配置上。
我测试的每个集群的大页面大小都不同。
一个正在分配 frag-tables 的集群是...
AnonHugePages: 208896 kB
HugePages_Total: 8
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 1048576 kB
当我尝试分配 frag-tables 时,另一个集群不断返回分段错误......
AnonHugePages: 6144 kB
HugePages_Total: 1024
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
这是按每个逻辑核心缩放 rx 和 tx 队列的基本性能,如您所见,可以使用多个 rx-tx 队列,每个队列都与带有逻辑核心的 frag-table 相关联,并且所需的池。
您好 Whosebug 专家,
我无法在多核中应用 ip 分段。
我的最终问题是是否可以为每个不同的直接和间接池分配多个 ip 碎片 table。
如果有人能指出我在这里做错了什么或为我提供一些替代解决方案,我将非常感激。
目的
我正在尝试在多核中应用 ip 分段,并通过大于 MTU 的消息最大化吞吐量性能。
- 对于每个本地和远程主机(使用 1 到 8 个逻辑核心)
- 1 ~ 4 用于传输碎片消息
- 4 ~ 8 用于接收和 assemble 消息
- 正在从本地发送 4KB 消息
- 远程将消息回传给本地。
- 计算总吞吐量
问题
如果我尝试将碎片 table 分配给每个内核,则会出现分段错误,无论我缩小碎片 table 的大小都会发生这种情况。 我尝试分配池和 frag-table 的方式如下所示。
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 分配了多个碎片 table,但让直接和间接池一起共享。
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(...);
情况
现在,当我使用多个内核从本地向远程主机发送消息时,远程主机只有在我发送消息时才成功接收到消息,并添加延迟,例如(添加睡眠(1);对于每条消息发送。)我能够从本地接收消息到远程。但是,当我尝试立即发送数据时,无法接收到任何数据。
结论
就个人而言,我怀疑我应该为每个逻辑核心分配直接池和间接池,我认为这是主要问题。由于我只能使用一个逻辑核心成功使用 frag-table,我怀疑我没有在多个核心中正确使用碎片 table。
我真的很想听听 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
1。请提供源代码
这将帮助您得到答案,而不是猜测 ;)
2。片段 Table 与 lcores
DPDK程序员指南明确指出:
all update/lookup operations on Fragment Table are not thread safe.
因此每个 lcore 必须有自己的片段 table 否则必须使用锁。
3。内存池与 lcores
默认情况下,DPDK 中的内存池是线程安全的,除非我们传递像 MEMPOOL_F_SP_PUT
这样的标志。所以,回答你的问题:
whether it is possible to have multiple ip fragmentation table allocated with each different direct and indirect pool.
默认情况下,很少有 lcores 可以共享内存池。
4。猜猜!
由于没有源代码,所以我猜根本原因是片段的 TTL 小于 1 秒,所以 sleep(1)
数据包到达太晚无法重新组装。
5。旁注
重新组装是非常耗时且 space 的操作,应不惜一切代价避免。
考虑一些方法,通过更改协议或使用巨型帧将您的消息装入一个数据包。
答案是一个非常基本的答案.. 问题出在大页面的配置上。 我测试的每个集群的大页面大小都不同。
一个正在分配 frag-tables 的集群是...
AnonHugePages: 208896 kB
HugePages_Total: 8
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 1048576 kB
当我尝试分配 frag-tables 时,另一个集群不断返回分段错误......
AnonHugePages: 6144 kB
HugePages_Total: 1024
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
这是按每个逻辑核心缩放 rx 和 tx 队列的基本性能,如您所见,可以使用多个 rx-tx 队列,每个队列都与带有逻辑核心的 frag-table 相关联,并且所需的池。