DPDK-REORDER LIBRARY 排序库

来源:互联网 发布:win7碎片整理软件 编辑:程序博客网 时间:2024/06/15 10:35

0x01 缘由

     排序,不要与tcp流重组排序混淆,而且下文踢桃序列号和tcp序列号不是同一个。此库为非线程安全的。

0x02 介绍

     1.引言

     Reorder Library 提供一种机制依据序列号对mbuf进行排序。

     2.操作

     Reorder Library实质上是一个mbuf有序buffer。使用者将乱序的mbuf插入到有序的buffer中,然后从中有序的取出。
     在给定时间内,这个重排buffer包含序列号在序列窗口内的mbufs。序列窗口由最小序列数和重排序buffer配置的持有条目数决定。例如,给一个有200条目的重排序buffer和350的最小序列,这个序列窗口最小值和最大值分别为350,550。
     当插入mbufs时,Reorder Library依赖插入在mbuf中序列号来区分先后的有效性:
     vaild: 序列号在窗口内。
     late: 序列号在窗口外,小于最小序列号。
     early:序列号在窗口外,大于最大序列号。
     重排buffer直接返回late mbufs,然后尝试容纳early mbufs。

     3.实现细节

     Reorder Library 实现一对缓冲区,称为Oder buffer 和Ready buffer。
     调用一个插入方法,vaild mbufs是直接插入到Oder buffer,而late mbufs是直接返回一个错误信息。
     对于early mbufs这种情况下,重新排序buffer将尝试移动窗口(递增最小序列号),以使mbuf变为有效的。为此,在Oder buffer中mbufs被移到Ready buffer中。任何mbufs没有及时到达的将被忽略,因此将变为late mbufs。这意味着只要Ready buffer中有多余的空间,窗口就会移动来容纳early mbufs,否则就会在重排窗口之外。
     例如,假设有一个200条目和最小序列为350的重排buffer,然后我们需要差异个序号为565的early mbuf。这说明我们至少需要移动窗口15个位置去容纳这个mbuf。这个重排buffer尝试移动mbufs在Order buffer中15个槽到Ready buffer中,只要Ready buffer中有足够的空间。在这个点的Order buffer的任何空隙将调过,当后面到来的包将被当做late包。将数据包移动Ready buffer过程持续到最小值知道一个空隙,如在Order buffer 遇到丢包。
     当处理mbufs过程时,这个重排buffer将先把Ready buffer中的mbuf返回,然后Order buffer中的直到遇到丢包。

0x03 应用

     案例:包分发器
     使用DPDK实现一个包分发器的应用,利用到Reorder Library库按包接收的顺序去转发数据包。
     一个基本的包分发器由一个分发器和多个worker线程组成。这个worker线程无法保证包有序的,因此一个重排序缓存能够尽可能的讲包排序处理。
     在这种场景下,在将mbufs派送到works前,包分发器分配一个序列号到mbuf。当works完成包处理时,这个包分发器插入这个mbufs到重排序buffer,然后最后转发到处理mbufs。

0x04 DPDK example

[root@dev packet_ordering]# lsbuild  main.c  Makefile[root@dev packet_ordering]# make clean[root@dev packet_ordering]# make  CC main.o  LD packet_ordering  INSTALL-APP packet_ordering  INSTALL-MAP packet_ordering.map

       /* Create rings for inter core communication */        rx_to_workers = rte_ring_create("rx_to_workers", RING_SIZE, rte_socket_id(),                        RING_F_SP_ENQ);        if (rx_to_workers == NULL)                rte_exit(EXIT_FAILURE, "%s\n", rte_strerror(rte_errno));        workers_to_tx = rte_ring_create("workers_to_tx", RING_SIZE, rte_socket_id(),                        RING_F_SC_DEQ);        if (workers_to_tx == NULL)                rte_exit(EXIT_FAILURE, "%s\n", rte_strerror(rte_errno));        if (!disable_reorder) {                send_args.buffer = rte_reorder_create("PKT_RO", rte_socket_id(),                                REORDER_BUFFER_SIZE);                if (send_args.buffer == NULL)                        rte_exit(EXIT_FAILURE, "%s\n", rte_strerror(rte_errno));        }        last_lcore_id   = get_last_lcore_id();        master_lcore_id = rte_get_master_lcore();        worker_args.ring_in  = rx_to_workers;        worker_args.ring_out = workers_to_tx;        /* Start worker_thread() on all the available slave cores but the last 1 */        for (lcore_id = 0; lcore_id <= get_previous_lcore_id(last_lcore_id); lcore_id++)                if (rte_lcore_is_enabled(lcore_id) && lcore_id != master_lcore_id)                        rte_eal_remote_launch(worker_thread, (void *)&worker_args,                                        lcore_id);        if (disable_reorder) {                /* Start tx_thread() on the last slave core */                rte_eal_remote_launch((lcore_function_t *)tx_thread, workers_to_tx,                                last_lcore_id);        } else {                send_args.ring_in = workers_to_tx;                /* Start send_thread() on the last slave core */                rte_eal_remote_launch((lcore_function_t *)send_thread,                                (void *)&send_args, last_lcore_id);        }        /* Start rx_thread() on the master core */        rx_thread(rx_to_workers);



原创粉丝点击