当前位置: 首页 > news >正文

四、程序员指南:数据平面开发套件

REORDER LIBRARY

重排序库提供了根据其序列号对mbuf进行重排序的机制。

16.1 操作

重排序库本质上是一个对mbuf进行重新排序的缓冲区。用户将乱序的mbuf插入重排序缓冲区,并从中提取顺序正确的mbuf。
在任何给定时刻,重排序缓冲区包含其序列号位于序列窗口内的mbuf。序列窗口由最小序列号和缓冲区配置为保存的条目数确定。例如,给定一个具有200个条目和最小序列号为350的重排序缓冲区,序列窗口的低限和高限分别为350和550。
在插入mbuf时,重排序库根据插入mbuf的序列号区分有效、晚到和早到的mbuf:

  • 有效:序列号在窗口内。
  • 晚到:序列号超出窗口且小于低限。
  • 早到:序列号超出窗口且大于高限。
    重排序缓冲区直接返回晚到的mbuf,并尝试容纳早到的mbuf。

16.2 实现细节

重排序库实现为一对缓冲区,分别称为Order缓冲区和Ready缓冲区。
在插入调用时,有效的mbuf直接插入Order缓冲区,而晚到的mbuf则以错误的形式返回给用户。
对于早到的mbuf,重排序缓冲区将尝试移动窗口(递增最小序列号),使mbuf变为有效。为此,将Order缓冲区中的mbuf移动到Ready缓冲区。尚未到达的mbuf将被忽略,因此将成为晚到的mbuf。这意味着只要Ready缓冲区有空间,窗口就会移动以容纳本应在重排序窗口外的早到mbuf。
例如,假设我们有一个包含200个条目、最小序列号为350的缓冲区,并且我们需要插入序列号为565的早到mbuf。这意味着我们需要至少移动窗口15个位置来容纳该mbuf。重排序缓冲区会尝试从Order缓冲区的至少接下来的15个插槽中移动mbuf到Ready缓冲区,只要Ready缓冲区有空间。在此时,Order缓冲区中的任何间隙都将被跳过,并且这些数据包在到达时将被报告为晚到的数据包。将数据包移动到Ready缓冲区的过程会持续超过最小要求,直到在Order缓冲区中遇到间隙(即丢失的mbuf)为止。
在排空mbuf时,重排序缓冲区首先从Ready缓冲区返回mbuf,然后从Order缓冲区返回,直到找到间隙(尚未到达的mbuf)为止。

16.3 Use Case: Packet Distributor

使用DPDK数据包分发器的应用程序可以利用重排序库以按接收顺序传输数据包。
一个基本的数据包分发器用例包括具有多个工作核心的分发器。工作核心对数据包的处理不能保证顺序,因此可以使用重排序缓冲区对尽可能多的数据包进行排序。
在这种情况下,分发器在将数据包传递给工作核心之前为mbuf分配序列号。随着工作核心完成处理数据包,分发器将这些mbuf插入重排序缓冲区,最后传输排空的mbuf。
注意:当前的重排序缓冲区不是线程安全的,因此同一个线程负责插入和排空mbuf。

IP FRAGMENTATION AND REASSEMBLY LIBRARY

IP Fragmentation and Reassembly Library实现了IPv4和IPv6数据包的分片和重组。

17.1 数据包分片

数据包分片例程将输入数据包分成多个片段。rte_ipv4_fragment_packet()rte_ipv6_fragment_packet()函数假设输入的mbuf数据指向数据包的IP头的起始位置(即L2头已经被剥离)。为避免对实际数据包数据进行复制,使用了零拷贝技术(rte_pktmbuf_attach)。
对于每个片段,创建了两个新的mbuf:

  • 直接mbuf:将包含新片段的L3头。
  • 间接mbuf:附加到具有原始数据包的mbuf上。它的数据字段指向原始数据包数据的起始位置加上片段偏移量。
    然后,将原始mbuf中的L3头复制到“直接”mbuf中,并更新以反映新的分片状态。注意,对于IPv4,不会重新计算头部校验和,而是设置为零。
    最后,通过mbuf的next字段将每个片段的“直接”和“间接”mbuf链接在一起,以组成新片段的数据包。
    调用者可以显式指定应从中分配“直接”和“间接”mbuf的内存池。
    有关直接和间接mbuf的更多信息,请参阅DPDK程序员指南7.7 Direct and Indirect Buffers。

17.2 数据包重组

17.2.1 IP分片表

分片表维护关于已接收到数据包片段的信息。
每个IP数据包由三元组 <源IP地址>、<目标IP地址>、 唯一标识。
需要注意的是,对分片表的所有更新/查找操作都不是线程安全的。因此,如果不同的执行上下文(线程/进程)同时访问相同的表,则必须提供某种外部同步机制。
每个表条目可以包含最多 RTE_LIBRTE_IP_FRAG_MAX(默认值为4)个片段的信息。
示例代码演示了如何创建一个新的分片表:

frag_cycles = (rte_get_tsc_hz() + MS_PER_S - 1) / MS_PER_S * max_flow_ttl;
bucket_num = max_flow_num + max_flow_num / 4;
frag_tbl = rte_ip_frag_table_create(max_flow_num, bucket_entries,
max_flow_num, frag_cycles, socket_id);

内部分片表是一个简单的哈希表。基本思想是使用两个哈希函数和 <bucket_entries> * 关联性。这为每个键提供了 2 * <bucket_entries> 个可能的位置。当发生冲突并且所有 2 * <bucket_entries> 位置都被占用时,ip_frag_tbl_add() 不会重新插入现有键到备用位置,而只是返回失败。
此外,驻留在表中时间超过 <max_cycles> 的条目被视为无效,并且可以被新条目删除/替换。
需要注意的是,重组需要大量的mbuf进行分配。在任何给定时间内,最多可以在分片表中存储 (2 * bucket_entries * RTE_LIBRTE_IP_FRAG_MAX * <每个数据包的最大mbuf数>) 个片段等待其余片段的到来。

17.2.2 数据包重组

分片数据包的处理和重组由rte_ipv4_frag_reassemble_packet() / rte_ipv6_frag_reassemble_packet()函数完成。这些函数要么返回包含重组数据包的有效mbuf指针,要么返回NULL(如果由于某种原因无法重组数据包)。

这些函数负责:

  1. 在分片表中查找具有数据包的<IPv4源地址,IPv4目标地址,数据包ID>的条目。
  2. 如果找到条目,则检查该条目是否已超时。如果是,则释放所有先前接收到的片段,并从条目中删除与它们相关的信息。
  3. 如果没有找到具有此键的条目,则尝试通过以下两种方式之一创建新条目:
    (a) 使用空条目。
    (b) 删除超时条目,释放与其关联的mbuf,并在其中存储具有指定键的新条目。
  4. 更新条目以包含新的片段信息,并检查是否可以重新组装数据包(数据包的条目包含所有片段)。
    (a) 如果可以,那么重新组装数据包,将表的条目标记为空,并将重组的mbuf返回给调用者。
    (b) 如果不能,则向调用者返回NULL。

如果在数据包处理的任何阶段遇到错误(例如:无法将新条目插入分片表,或者无效/超时的片段),则函数将释放与数据包关联的所有片段,将表条目标记为无效,并向调用者返回NULL。

17.2.3 调试日志记录和统计收集

RTE_LIBRTE_IP_FRAG_TBL_STAT配置宏控制分片表的统计收集。默认情况下,此宏未启用。
RTE_LIBRTE_IP_FRAG_DEBUG控制IP片段处理和重组的调试日志记录。默认情况下,此宏已禁用。需要注意的是,尽管日志包含大量详细信息,但它会减慢数据包处理速度,并可能导致大量数据包丢失。

MULTI-PROCESS SUPPORT

在DPDK中,多进程支持旨在允许一组DPDK进程在Intel®架构硬件上以简单透明的方式共同执行数据包处理或其他工作负载。为支持此功能,对核心DPDK环境抽象层(EAL)进行了一些增加。

EAL已被修改以允许生成不同类型的DPDK进程,每个进程对应用程序使用的hugepage内存具有不同的权限。目前有两种指定的进程类型:

  • 主进程:可以初始化并具有对共享内存的全部权限。
  • 次要进程:无法初始化共享内存,但可以附加到预先初始化的共享内存并在其中创建对象。

独立的DPDK进程是主进程,而次要进程只能在主进程旁边运行或在主进程已为其配置了hugepage共享内存后运行。

为支持这两种进程类型和后续描述的其他多进程设置,EAL提供了两个额外的命令行参数:

  • –proc-type:用于指定给定进程实例为主要或次要DPDK实例。
  • –file-prefix:允许不想合作的进程具有不同的内存区域。

提供了许多示例应用程序,演示了如何一起使用多个DPDK进程。这些在“DPDK示例应用程序用户指南”的“多进程示例应用程序”章节中有更详细的文档记录。

18.1 内存共享

使用DPDK创建多进程应用程序的关键要素是确保内存资源在构成多进程应用程序的各个进程之间得到正确共享。一旦有多个进程可以访问的共享内存块,那么诸如进程间通信(IPC)之类的问题就变得简单得多。

在主要或独立进程的应用程序启动时,DPDK将内存配置的详细信息记录到内存映射文件中 - 使用的hugepages,它们映射的虚拟地址,存在的内存通道数等。当启动次要进程时,会读取这些文件,EAL会在次要进程中重新创建相同的内存配置,以便所有内存区域在进程之间共享,并且所有对该内存的指针在两个进程中都是有效的,并且指向相同的对象。

注意:有关Linux内核地址空间布局随机化(ASLR)如何影响内存共享的详细信息,请参阅多进程限制部分。
在这里插入图片描述
Figure 18.1: Memory Sharing in the DPDK Multi-process Sample Application
EAL还支持自动检测模式(通过EAL的 --proc-type=auto 标志设置),如果已经运行了主要实例,则会启动一个DPDK进程作为次要实例。

18.2 部署模型

18.2.1 对称/对等进程

DPDK多进程支持可用于创建一组对等进程,其中每个进程执行相同的工作负载。该模型相当于具有多个线程,每个线程都运行相同的主循环功能,这是大多数提供的DPDK示例应用程序所做的。在此模型中,首个生成的进程应使用 --proc-type=primary EAL标志生成,而所有后续实例应使用 --proc-type=secondary 标志生成。

simple_mp 和 symmetric_mp 示例应用程序展示了这种用法模型。它们在“DPDK示例应用程序用户指南”的“多进程示例应用程序”章节中有描述。

18.2.2 非对称/非对等进程

多进程应用程序的另一种可用部署模型是拥有一个充当负载均衡器或服务器的单个主进程实例,将接收到的数据包分发给作为次要进程运行的工作线程或客户端线程。在这种情况下,广泛使用了位于共享hugepage内存中的rte_ring对象。

client_server_mp 示例应用程序展示了这种用法模型。它在“DPDK示例应用程序用户指南”的“多进程示例应用程序”章节中有描述。

18.2.3 运行多个独立的DPDK应用程序

除了涉及多个DPDK进程共同工作的上述情景之外,还可以在旁边运行多个独立的DPDK进程,这些进程都在独立工作。支持此使用场景的方法是使用EAL的 --file-prefix 参数。

默认情况下,EAL在每个hugetlbfs文件系统上创建hugepage文件,文件名为rtemap_X,其中X的范围是从0到最大hugepages - 1。类似地,当以root用户运行时(或以非root用户运行时,如果文件系统和设备权限设置允许的话),它会创建共享配置文件,每个进程中都有内存映射,文件名为/var/run/.rte_config,文件名中的rte部分可以使用file-prefix参数进行配置。

除了指定file-prefix参数之外,任何要并行运行的DPDK应用程序都必须明确限制其内存使用。这通过向每个进程传递 -m 标志来实现,以指定每个进程可以使用多少兆字节的hugepage内存(或传递 --socket-mem 以指定每个进程在每个插槽上可以使用多少hugepage内存)。

注意:在单个机器上并行运行的独立DPDK实例不能共享任何网络端口。任何一个进程使用的网络端口应在其他每个进程中列入黑名单。

18.2.4 运行多个独立DPDK应用程序组

与在单个系统上并行运行独立的DPDK应用程序类似,这可以轻松地扩展到并行运行多个DPDK应用程序组。在这种情况下,次要进程必须使用与其连接到的主要进程相同的 --file-prefix 参数。

注意:在此使用场景中,所有与并行运行的多个独立DPDK进程相关的限制和问题也适用。

18.3 多进程的限制

在运行DPDK多进程应用程序时存在一些限制。以下是其中一些已记录的限制:

  • 多进程功能要求所有应用程序中都存在完全相同的hugepage内存映射。Linux安全功能 - 地址空间布局随机化(ASLR)可能会干扰此映射,因此可能需要禁用此功能才能可靠地运行多进程应用程序。
    警告:禁用地址空间布局随机化(ASLR)可能会带来安全问题,因此建议仅在绝对必要时和在理解了此更改的影响后才禁用。

  • 所有作为单个应用程序运行并使用共享内存的DPDK进程必须具有不同的coremask参数。不可能有一个主要实例和次要实例,或者两个次要实例,使用相同的逻辑核心。试图这样做可能会导致内存池缓存的损坏,等其他问题。

  • 在次要进程中,例如以太网设备链接状态中断等中断的传递不起作用。所有中断仅在主进程内触发。
    任何需要在多个进程中进行中断通知的应用程序都应提供自己的机制,将中断信息从主进程传输到需要该信息的任何次要进程。

  • 在基于不同编译的二进制文件的多个进程之间使用函数指针是不受支持的,因为给定函数在一个进程中的位置可能与其在第二个进程中的位置不同。这会阻止librte_hash库的正常行为,因为它在内部使用指向哈希函数的指针,类似于多线程实例。
    为解决此问题,建议多进程应用程序通过直接从代码中调用哈希函数进行哈希计算,然后使用rte_hash_add_with_hash()/rte_hash_lookup_with_hash()函数,而不是使用内部执行哈希计算的函数,如rte_hash_add()/rte_hash_lookup()。

  • 根据正在使用的硬件和使用的DPDK进程数量,可能无法在每个DPDK实例中使用HPET定时器。Linux*用户空间可用的最小HPET比较器数量可能只有一个比较器,这意味着只有第一个主要DPDK进程实例可以打开并mmap /dev/hpet。如果所需的DPDK进程数量超过可用HPET比较器的数量,则必须在所有进程中使用TSC(在此版本中是默认定时器)作为时间源,而不是使用HPET。

DPDK内核NIC接口

DPDK(Data Plane Development Kit)内核NIC接口(KNI)允许用户空间应用程序访问Linux*控制平面。

使用DPDK KNI的好处有:

  • 比现有的Linux TUN/TAP接口更快(通过消除系统调用和copy_to_user()/copy_from_user()操作)。
  • 允许使用标准的Linux网络工具(如ethtool、ifconfig和tcpdump)管理DPDK端口。
  • 允许与内核网络堆栈进行接口。

使用DPDK内核NIC接口的应用程序组件如图19.1所示。

19.1 DPDK KNI内核模块

KNI内核可加载模块支持两种类型的设备:

  • 杂项设备(/dev/kni):
    • 通过ioctl调用创建网络设备。
    • 维护所有KNI实例共享的内核线程上下文(模拟网络驱动程序的RX端)。
    • 对于单个内核线程模式,维护所有KNI实例共享的内核线程上下文(模拟网络驱动程序的RX端)。
    • 对于多个内核线程模式,为每个KNI实例维护内核线程上下文(模拟新驱动程序的RX端)。
  • 网络设备
    • 通过实现多个操作(如netdev_ops、header_ops、ethtool_ops),提供网络功能,这些操作由struct net_device定义,包括对DPDK mbufs和FIFOs的支持。
    • 接口名称由用户空间提供。
    • MAC地址可以是真实的NIC MAC地址或随机生成的。
      在这里插入图片描述
      Figure 19.1: Components of a DPDK KNI Application

19.2 KNI创建和删除

KNI接口由DPDK应用程序动态创建。接口名称和FIFO详细信息由应用程序通过使用rte_kni_device_info结构的ioctl调用提供,其中包含:

  • 接口名称。
  • 相关FIFO的对应memzones的物理地址。
  • Mbuf内存池的详细信息,包括物理和虚拟地址(用于计算mbuf指针的偏移量)。
  • PCI信息。
  • 核心亲和性。
    请参阅DPDK源代码中的rte_kni_common.h以获取更多详细信息。
    这些物理地址将重新映射到内核地址空间,并存储在单独的KNI上下文中。
    一旦创建了KNI接口,可以通过调用rte_kni_info_get()函数查询KNI上下文信息。
    KNI接口可以在创建后由DPDK应用程序动态删除。
    此外,所有未被删除的KNI接口将在杂项设备的释放操作中被删除(当关闭DPDK应用程序时)。

19.3 DPDK mbuf流程

为了最小化在内核空间运行的DPDK代码量,mbuf内存池仅由用户空间管理。内核模块将了解mbuf,但所有的mbuf分配和释放操作将仅由DPDK应用程序处理。图19.2显示了一个典型的双向发送数据包的场景。

19.4 使用案例:入口

在DPDK的RX端,mbuf由PMD在RX线程上下文中分配。此线程将mbuf排入rx_q FIFO。KNI线程将轮询所有KNI活动设备以获取rx_q。如果出列一个mbuf,它将被转换为sk_buff,并通过netif_rx()发送到网络堆栈。出列的mbuf必须被释放,因此相同的指针将通过free_q FIFO发送回去。在同一主循环中,RX线程轮询此FIFO并在出列后释放mbuf。

19.5 使用案例:出口

对于数据包出口,DPDK应用程序必须首先排入多个mbuf以在内核端创建mbuf缓存。
在这里插入图片描述
Figure 19.2: Packet Flow via mbufs in the DPDK KNI
数据包通过调用kni_net_tx()回调从Linux网络堆栈接收。mbuf被出列(由于缓存而无需等待),并用sk_buff中的数据填充。然后释放sk_buff并将mbuf发送到tx_q FIFO。DPDK的TX线程出列mbuf并将其发送到PMD(通过rte_eth_tx_burst())。然后将mbuf放回缓存中。

19.6 Ethtool

Ethtool是一个特定于Linux的工具,在内核中具有相应的支持,每个网络设备必须为支持的操作注册自己的回调函数。当前的实现使用了修改后的igb/ixgbe Linux驱动程序以支持ethtool。在i40e和VM(VF或EM设备)中不支持Ethtool。

19.7 链路状态和MTU更改

链路状态和MTU更改是特定于网络接口的操作,通常通过ifconfig完成。请求是从内核端(在ifconfig进程的上下文中)发起的,并由用户空间的DPDK应用程序处理。应用程序轮询请求,调用应用程序处理程序,并将响应返回到内核空间。应用程序处理程序可以在接口创建时注册,也可以在运行时显式注册/注销。这在多进程场景中提供了灵活性(其中KNI在主进程中创建,但回调在辅助进程中处理)。约束是单个进程可以注册和处理请求。

19.8 KNI作为内核vHost后端

vHost是一个内核模块,通常作为virtio(一种para-虚拟化驱动框架)的后端,加速从客户机到主机的流量。DPDK内核NIC接口提供了将vHost流量连接到用户空间DPDK应用程序的功能。与DPDK PMD virtio一起使用,它显著改善了客户机和主机之间的吞吐量。在DPDK作为主机中的快速路径运行的情况下,kni-vhost是流量的高效路径。

19.8.1 概述

vHost-net有三种真实后端实现。它们是:1)tap,2)macvtap和3)RAW socket。kni-vhost背后的主要思想是使KNI作为RAW socket工作,将其附加为vHost-net的后端实例。它使用与vHost-net的现有接口,因此不需要任何内核修改,并且与内核vhost模块完全兼容。由于vHost仍然负责与前端virtio通信,因此它自然支持传统的virtio-net和DPDK PMD virtio。来自vhost非轮询模式的一点惩罚。但是,在使用多线程模式的KNI时,它能够很好地扩展吞吐量。
在这里插入图片描述
Figure 19.3: vHost-net Architecture Overview

19.8.2 数据包流动

与原始KNI流量流程相比,只有一个轻微的区别。在传输端,vhost kthread调用RAW socket的ops sendmsg,并将数据包放入KNI传输FIFO中。在接收端,kni kthread从KNI接收FIFO获取数据包,将它们放入原始套接字的队列中,并唤醒vhost kthread中的任务开始接收。无论是在传输端还是接收端,所有的数据包复制都发生在vhost kthread的上下文中。每个vhost-net设备都暴露给客户机中的一个前端virtio设备。
在这里插入图片描述
Figure 19.4: KNI Traffic Flow
9.8.3 示例用法
在开始使用KNI作为vhost的后端之前,必须打开CONFIG_RTE_KNI_VHOST配置选项。否则,默认情况下,KNI将不会启用其后端支持功能。

当然,作为先决条件,在编译内核之前应选择vhost/vhost-net内核CONFIG。

1.编译DPDK并像平常一样插入uio_pci_generic/igb_uio内核模块。

2.插入KNI内核模块:

insmod ./rte_kni.ko

如果在多线程模式下使用KNI,使用以下命令行:

insmod ./rte_kni.ko kthread_mode=multiple

3.运行KNI示例应用程序:

./kni -c -0xf0 -n 4 -- -p 0x3 -P -config="(0,4,6),(1,5,7)"

此命令在两个物理端口上运行kni示例应用程序。每个端口将在用户空间中钉住两个转发核心(入口/出口)。

4.在qemu-kvm启动时将原始套接字分配给vhost-net。由于DPDK没有提供执行此操作的脚本,因为用户可以轻松自定义。以下显示了启动带有kni-vhost的qemu-kvm的关键步骤:

#!/bin/bash
echo 1 > /sys/class/net/vEth0/sock_en
fd=$(cat /sys/class/net/vEth0/sock_fd)
qemu-kvm \
-name vm1 -cpu host -m 2048 -smp 1 -hda /opt/vm-fc16.img \
-netdev tap,fd=$fd,id=hostnet1,vhost=on \
-device virti-net-pci,netdev=hostnet1,id=net1,bus=pci.0,addr=0x4

使用sysfs的sock_en简单启用原始套接字,并在KNI设备节点下使用sock_fd获取原始套接字fd。

然后,使用带有-netdev选项的qemu-kvm命令将此类原始套接字fd分配为vhost的后端。

注意:关键字tap必须存在,因为qemu-kvm现在仅支持带有tap后端的vhost,所以我们通过现有的fd来欺骗qemu-kvm。

19.8.4 兼容性配置选项

在DPDK配置文件中有一个CONFIG_RTE_KNI_VHOST_VNET_HDR_EN配置选项。默认情况下,它设置为n,这意味着不启用virtio net头部,该头部用于支持附加功能(例如,csum offloadvlan offloadgeneric-segmentation等),因为kni-vhost目前不支持这些功能。

即使选项被打开,kni-vhost也将忽略头部包含的信息。在与客户机上的传统virtio一起工作时,最好使用ethtool -K关闭不支持的offload功能。否则,可能会出现诸如不正确的L4校验和错误等问题。

20. 线程安全性的DPDK函数

DPDK由几个库组成。这些库中的一些函数可以安全地同时从多个线程调用,而其他函数则不行。本节允许开发人员在构建自己的应用程序时考虑这些问题。

20.1 快速路径 API

在数据平面操作的应用程序对性能敏感,但这些库中的某些函数可能不适合同时从多个线程调用。哈希、LPM和内存池库以及PMD中的RX/TX就是这种情况的例子。

哈希和LPM库在设计上是线程不安全的,以保持性能。但是,如果需要,开发人员可以在这些库之上添加层以提供线程安全性。并非在所有情况下都需要锁定,在哈希和LPM库中,可以在多个线程中并行执行值的查找。但是,无法在多个线程中添加、删除或修改值,除非在访问单个哈希或LPM表时使用锁定。另一个替代锁定的方法是创建这些表的多个实例,允许每个线程拥有自己的副本。

PMD的RX和TX是DPDK应用程序最关键的部分,建议不要使用锁定,因为它会影响性能。但是,请注意,当每个线程在不同的NIC队列上执行I/O时,这些函数可以安全地从多个线程中使用。如果多个线程要在同一个NIC端口上使用相同的硬件队列,则需要锁定或其他形式的互斥。

环形缓冲区库基于无锁环形缓冲区算法,保持其原始设计以实现线程安全性。此外,它为多个或单个消费者/生产者的入队/出队操作提供高性能。内存池库基于DPDK无锁环形缓冲区库,因此也是多线程安全的。

20.2 不敏感于性能的API

在前一节中描述的性能敏感区域之外,DPDK为大多数其他库提供了线程安全的API。例如,malloc(librte_malloc)memzone函数在多线程和多进程环境中是安全的。

PMD的设置和配置既不敏感于性能,也不是线程安全的。在PMD设置和配置期间的多次读/写可能在多线程环境中会导致破坏。由于这不是性能敏感的,开发人员可以选择添加自己的层来提供线程安全的设置和配置。在大多数应用程序中,预计网络端口的初始配置将由单个线程在启动时完成。

20.3 库的初始化

建议在应用程序启动的主线程中初始化DPDK库,而不是在之后的转发线程中初始化。然而,DPDK执行检查以确保库只初始化一次。如果尝试多次初始化,则会返回错误。

在多进程的情况下,共享内存的配置信息只会被主进程初始化。之后,主进程和次要进程都可以分配/释放依赖于rte_mallocmemzones的任何内存对象。

20.4 中断线程

DPDK几乎完全在Linux用户空间中以轮询模式运行。对于某些不频繁的操作,例如接收PMD链路状态更改通知,回调可能会在主DPDK处理线程之外的额外线程中调用。这些函数回调应避免操纵也由常规DPDK线程管理的DPDK对象。如果它们需要这样做,就由应用程序提供适当的锁定或互斥约束来围绕这些对象。

相关文章:

四、程序员指南:数据平面开发套件

REORDER LIBRARY 重排序库提供了根据其序列号对mbuf进行重排序的机制。 16.1 操作 重排序库本质上是一个对mbuf进行重新排序的缓冲区。用户将乱序的mbuf插入重排序缓冲区&#xff0c;并从中提取顺序正确的mbuf。 在任何给定时刻&#xff0c;重排序缓冲区包含其序列号位于序列…...

Go 之 captcha 生成图像验证码

目前 chptcha 好像只可以生成纯数字的图像验证码&#xff0c;不过对于普通简单应用来说也足够了。captcha默认将store封装到内部&#xff0c;未提供对外操作的接口&#xff0c;因此使用自己显式生成的store&#xff0c;可以通过store自定义要生成的验证码。 package mainimpor…...

【Java从入门到大牛】多线程

&#x1f525; 本文由 程序喵正在路上 原创&#xff0c;CSDN首发&#xff01; &#x1f496; 系列专栏&#xff1a;Java从入门到大牛 &#x1f320; 首发时间&#xff1a;2023年11月18日 &#x1f98b; 欢迎关注&#x1f5b1;点赞&#x1f44d;收藏&#x1f31f;留言&#x1f4…...

UE5 C++报错:is not currently enabled for Live Coding

解决办法&#xff1a; 再次打开项目&#xff0c;以此法打开&#xff1a;...

mysql服务器数据同步

在Linux和Windows之间实现MySQL服务器数据的同步。下面是一些常见的方法和工具&#xff1a; 复制&#xff08;Replication&#xff09;&#xff1a;MySQL复制是一种常见的数据同步技术&#xff0c;可用于将一个MySQL服务器的数据复制到其他服务器。您可以设置主服务器&#xff…...

Docker Golang 开发环境搭建指南

Docker Golang 开发环境搭建指南 概述 在 Golang 开发中&#xff0c;搭建合适的开发环境是非常重要的。然而&#xff0c;由于 Golang 的跨平台特性&#xff0c;不同操作系统之间的配置差异可能会导致环境搭建过程变得复杂。为了简化这个过程并保持开发环境的一致性&#xff0…...

MFC保存窗口客户区为图片

首先的窗口输出一些内容&#xff1b; 菜单单击函数代码&#xff1b; void CgetmypicView::OnTestGetmypic() {// TODO: 在此添加命令处理程序代码HWND hwnd this->GetSafeHwnd();HDC hDC ::GetWindowDC(hwnd);//获取DC RECT rect;::GetClientRect(hwnd, &rect)…...

JAVA安全之Shrio550-721漏洞原理及复现

前言 关于shrio漏洞&#xff0c;网上有很多博文讲解&#xff0c;这些博文对漏洞的解释似乎有一套约定俗成的说辞&#xff0c;让人云里来云里去&#xff0c;都没有对漏洞产生的原因深入地去探究..... 本文从现象到本质&#xff0c;旨在解释清楚Shrio漏洞是怎么回事&#xff01…...

有Mac或无Mac电脑通用的获取安卓公钥的方案

从2023年9月开始&#xff0c;所有上架应用市场的app都需要进行APP备案。 其中后端服务器在阿里云的可以在阿里云备案&#xff0c;后端服务器在腾讯云的可以在腾讯云备案。但无论你是在什么云厂商里做备案&#xff0c;无一例外的是&#xff0c;无论是上架安卓应用还是上架IOS应…...

电池故障估计:Realistic fault detection of li-ion battery via dynamical deep learning

昇科能源、清华大学欧阳明高院士团队等的最新研究成果《动态深度学习实现锂离子电池异常检测》&#xff0c;用已经处理的整车充电段数据&#xff0c;分析车辆当前或近期是否存在故障。 思想步骤&#xff1a; 用正常电池的充电片段数据构造训练集&#xff0c;用如下的方式构造…...

微服务和Spring Cloud Alibaba介绍

1、微服务介绍 1.1 系统架构演变 随着互联网的发展&#xff0c;网站应用的规模也在不断的扩大&#xff0c;进而导致系统架构也在不断的进行变化。从互联网早起到现在&#xff0c;系统架构大体经历了下面几个过程: 单体应用架构 —> 垂直应用架构 —> 分布 式架构—>…...

【js】 lodash命名转换和封装

▒ 目录 ▒ &#x1f6eb; 导读需求开发环境 1️⃣ lodash转换函数h3与underscore比较 2️⃣ 实战&#xff1a;对象属性名转换函数封装单元测试 &#x1f6ec; 文章小结&#x1f4d6; 参考资料 &#x1f6eb; 导读 需求 爬虫中经常出现各种类型的命名&#xff0c;往往一个对象…...

RK3568驱动指南|第七篇 设备树-第67章 of操作函数实验:获取属性

瑞芯微RK3568芯片是一款定位中高端的通用型SOC&#xff0c;采用22nm制程工艺&#xff0c;搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码&#xff0c;支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU&#xff0c;可用于轻量级人工…...

vue3安装vue-router

环境 node 18.14.2 yarn 1.22.19 windows 11 vite快速创建vue项目 参考 安装vue-touter 官网 yarn add vue-router4src下新建router文件夹&#xff0c;该文件夹下新建index.ts // router/index.ts 文件 import { createRouter, createWebHashHistory, RouterOptions, Ro…...

〖大前端 - 基础入门三大核心之JS篇㊱〗- JavaScript 的DOM节点操作

说明&#xff1a;该文属于 大前端全栈架构白宝书专栏&#xff0c;目前阶段免费&#xff0c;如需要项目实战或者是体系化资源&#xff0c;文末名片加V&#xff01;作者&#xff1a;不渴望力量的哈士奇(哈哥)&#xff0c;十余年工作经验, 从事过全栈研发、产品经理等工作&#xf…...

【计算机基础】优雅的PPT就应该这样设计

&#x1f4e2;&#xff1a;如果你也对机器人、人工智能感兴趣&#xff0c;看来我们志同道合✨ &#x1f4e2;&#xff1a;不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 &#x1f4e2;&#xff1a;文章若有幸对你有帮助&#xff0c;可点赞 &#x1f44d;…...

Vatee万腾的科技征程:Vatee数字化创新的前沿探讨

在Vatee万腾的科技征程中&#xff0c;我们目睹了一场数字化创新的引领之旅&#xff0c;探讨了Vatee在科技前沿的独到见解。Vatee万腾不仅仅是一家科技公司&#xff0c;更是一支前行不辍的冒险队伍&#xff0c;通过不断突破自我&#xff0c;探索未知领域&#xff0c;引领着数字化…...

【PB续命05】WinHttp.WinHttpRequest的介绍与使用

0 WinHttp.WinHttpRequest简介 winhttp.winhttprequest是Windows操作系统中的一个API函数&#xff0c;用于创建和发送HTTP请求。它可以用于从Web服务器获取数据&#xff0c;或将数据发送到Web服务器。该函数提供了许多选项&#xff0c;例如设置请求头、设置代理服务器、设置超…...

【Linux】进程间是这样通信的--管道篇

TOC 目录 进程间通信的介绍 进程间通信的概念 进程间通信的目的 进程间通信的本质 进程间通信的分类 管道 什么是管道 匿名管道 pipe函数 匿名管道使用步骤 管道读写规则 管道的特点 1、管道内部自带同步与互斥机制 2、管道的生命周期随进程 3、管道提供的是流式…...

Python基础入门例程60-NP60 跳过列表的某个元素(循环语句)

最近的博文: Python基础入门例程59-NP59 提前结束的循环(循环语句)-CSDN博客 Python基础入门例程58-NP58 找到HR(循环语句)-CSDN博客 Python基础入门例程57-NP57 格式化清单(循环语句)-CSDN博客 目录 最近的博文: 描述...

三十二、W5100S/W5500+RP2040树莓派Pico<UPnP示例>

文章目录 1 前言2 简介2 .1 什么是UPnP&#xff1f;2.2 UPnP的优点2.3 UPnP数据交互原理2.4 UPnP应用场景 3 WIZnet以太网芯片4 UPnP示例概述以及使用4.1 流程图4.2 准备工作核心4.3 连接方式4.4 主要代码概述4.5 结果演示 5 注意事项6 相关链接 1 前言 随着智能家居、物联网等…...

2023.11.18 Hadoop之 YARN

1.简介 Apache Hadoop YARN &#xff08;Yet Another Resource Negotiator&#xff0c;另一种资源协调者&#xff09;是一种新的 Hadoop 资源管理器&#xff0c;它是一个通用资源管理系统和调度平台&#xff0c;可为上层应用提供统一的资源管理和调度。支持多个数据处理框架&…...

ceph 常用命令

bucket 常用命令 查看 realm &#xff08;区域&#xff09; radosgw-admin realm list输出 {"default_info": "43c462f5-5634-496e-ad4e-978d28c2x9090","realms": ["myrgw"] }radosgw-admin realm get{"id": "2cfc…...

6.8完全二叉树的节点个数(LC222-E)

算法&#xff1a; 如果不考虑完全二叉树的特性&#xff0c;直接把完全二叉树当作普通二叉树求节点数&#xff0c;其实也很简单。 递归法&#xff1a; 用什么顺序遍历都可以。 比如后序遍历&#xff08;LRV&#xff09;&#xff1a;不断遍历左右子树的节点数&#xff0c;最后…...

基于协作mimo系统的RM编译码误码率matlab仿真,对比硬判决译码和软判决译码

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 ..................................................................... while(Err < TL…...

Django模型层

模型层 与数据库相关的&#xff0c;用于定义数据模型和数据库表结构。 在Django应用程序中&#xff0c;模型层是数据库和应用程序之间的接口&#xff0c;它负责处理所有与数据库相关的操作&#xff0c;例如创建、读取、更新和删除记录。Django的模型层还提供了一些高级功能 首…...

计算机视觉的应用18-一键抠图人像与更换背景的项目应用,可扩展批量抠图与背景替换

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下计算机视觉的应用18-一键抠图人像与更换背景的项目应用&#xff0c;可扩展批量抠图与背景替换。该项目能够让你轻松地处理和编辑图片。这个项目的核心功能是一键抠图和更换背景。这个项目能够自动识别图片中的主体&…...

Redis(哈希Hash和发布订阅模式)

哈希是一个字符类型字段和值的映射表。 在Redis中&#xff0c;哈希是一种数据结构&#xff0c;用于存储键值对的集合。哈希可以理解为一个键值对的集合&#xff0c;其中每个键都对应一个值。哈希在Redis中的作用主要有以下几点&#xff1a; 1. 存储对象&#xff1a;哈希可以用…...

php正则表达式汇总

php正则表达式有"/pattern/“、”“、”$“、”.“、”[]“、”[]“、”[a-z]“、”[A-Z]“、”[0-9]“、”\d"、“\D”、“\w”、“\W”、“\s”、“\S”、“\b”、“*”、“”、“?”、“{n}”、“{n,}”、“{n,m}”、“\bword\b”、“(pattern)”、“x|y"和…...

Python与ArcGIS系列(八)通过python执行地理处理工具

目录 0 简述1 脚本执行地理处理工具2 在地理处理工具间建立联系0 简述 arcgis包含数百种可以通过python脚本执行的地理处理工具,这样就通过python可以处理复杂的工作和批处理。本篇将介绍如何利用arcpy实现执行地理处理工具以及在地理处理工具间建立联系。 1 脚本执行地理处理…...

cocos----刚体

刚体&#xff08;Rigidbody&#xff09; 刚体&#xff08;Rigidbody&#xff09;是运动学&#xff08;Kinematic&#xff09;中的一个概念&#xff0c;指在运动中和受力作用后&#xff0c;形状和大小不变&#xff0c;而且内部各点的相对位置不变的物体。在 Unity3D 中&#xff…...

【SAP-HCM】--HR人员信息导入函数

人员基本信息导入函数&#xff1a;HR_MAINTAIN_MASTERDATA 人员其他信息类型导入函数&#xff1a;HR_INFOTYPE_OPERATION 不逼逼&#xff0c;直接上代码&#xff0c;这两个函数还是相对简单易懂的 *根据操作类型查找对应的T529A 操作类型对应的值IF gt_alv IS NOT INITIAL.S…...

【开源】基于JAVA的大学兼职教师管理系统

项目编号&#xff1a; S 004 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S004&#xff0c;文末获取源码。} 项目编号&#xff1a;S004&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、研究内容三、界面展示3.1 登录注册3.2 学生教师管…...

Pyhon函数

import time # # for i in range(1,10): # j1 # for j in range(1,i1): # print(f"{i}x{j}{i*j} " ,end) # print() #复用&#xff0c;代码&#xff0c;精简&#xff0c;复用度高def j99(n1,max10): for i in range(n,max):jifor j in ran…...

使用vuex完成小黑记事本案例

使用vuex完成小黑记事本案例 App.vue <template><div id"app"><TodoHeader></TodoHeader><TodoMain ></TodoMain><TodoFooter></TodoFooter></div> </template><script> import TodoMain from …...

进阶理解:leetcode115.不同的子序列(细节深度)

这道题是困难题&#xff0c;本章是针对于动态规划解决&#xff0c;对于思路进行一个全面透彻的讲解&#xff0c;但是并不是对于基础讲解思路&#xff0c;而是渗透到递推式和dp填数的详解&#xff0c;如果有读者不清楚基本的解题思路&#xff0c;请看我的这篇文章算法训练营DAY5…...

数据结构-哈希表(C语言)

哈希表的概念 哈希表就是&#xff1a; “将记录的存储位置与它的关键字之间建立一个对应关系&#xff0c;使每个关键字和一个唯一的存储位置对 应。” 哈希表又称&#xff1a;“散列法”、“杂凑法”、“关键字&#xff1a;地址法”。 哈希表思想 基本思想是在关键字和存…...

HCIA-综合实验(三)

综合实验&#xff08;三&#xff09; 1 实验拓扑2 IP 规划3 实验需求一、福州思博网络规划如下&#xff1a;二、上海思博网络规划如下&#xff1a;三、福州思博与上海思博网络互联四、网络优化 4 配置思路4.1 福州思博配置在 SW1、SW2、SW3 上配置交换网络SW1、SW2、SW3 运行 S…...

Java程序员的成长路径

熟悉JAVA语言基础语法。 学习JAVA基础知识&#xff0c;推荐阅读书单中的经典书籍。 理解并掌握面向对象的特性&#xff0c;比如继承&#xff0c;多态&#xff0c;覆盖&#xff0c;重载等含义&#xff0c;并正确运用。 熟悉SDK中常见类和API的使用&#xff0c;比如&#xff1…...

几种常用的排序

int[] arr new int[]{1, 2,8, 7, 5};这是提前准备好的数组 冒泡排序 public static void bubbleSort(int[] arr) {int len arr.length;for (int i 0; i < len - 1; i) {for (int j 0; j < len - i - 1; j) {if (arr[j] > arr[j1]) {int temp arr[j];arr[j] ar…...

性能测试【第三篇】Jmeter的使用

线程数:10 ,设置10个并发 Ramp-Up时间(秒):所有线程在多少时间内启动,如果设置5,那么每秒启动2个线程 循环次数:请求的重复次数,如果勾选"永远"将一直发送请求 持续时间时间:设置场景运行的时间 启动延迟:设置场景延迟启动时间 响应断言 响应断言模式匹配规则 包括…...

业务:业务系统检查项参考

名录明细云平台摸底1.原有云平台体系&#xff1a;VMware、openstack、ovirt、k8s、docker、混合云系列及版本 2.原有云平台规模&#xff0c;物理机数量、虚拟机数量、迁移业务系统所占配额 3.待补充系统摸底 (适用于物理主机)每一台虚拟机或物理机&#xff1a; 1.系统全局参数…...

解决公网下,k8s calico master节点无法访问node节点创建的pod

目的&#xff1a;解决pod部署成功后&#xff0c;只能在node节点访问&#xff0c;而master节点无法访问 原因&#xff1a;集群搭建时&#xff0c;没有配置公网进行kubectl操作&#xff0c;从而导致系统默认node节点&#xff0c;使用内网IP加入k8s集群&#xff01;如下&#xff…...

六边形架构

Alistair Cockburn是于1953年出生在美国的一位软件开发方法学家。他毕业于康奈尔大学计算机科学专业&#xff0c;并获得了博士学位。 Cockburn在敏捷软件开发领域做出了许多重要的贡献&#xff0c;他被广泛认可为敏捷方法学的奠基人之一。他提出了许多关于敏捷开发的原则和实践…...

基于单片机的智能家居安保系统(论文+源码)

1.系统设计 本次基于单片机的智能家居安保系统设计&#xff0c;在功能上如下&#xff1a; 1&#xff09;以51单片机为系统控制核心&#xff1b; 2&#xff09;温度传感器、人体红外静释电、烟雾传感器来实现检测目的&#xff1b; 3&#xff09;以GSM模块辅以按键来实现远/近程…...

盘点3种Python网络爬虫过程中的中文乱码的处理方法

网络爬虫过程中三种中文乱码的处理方案&#xff0c;希望对大家的学习有所帮助 一、思路 其实解决问题的关键点就是在于一点&#xff0c;就是将乱码的部分进行处理&#xff0c;而处理的方案主要可以从两个方面进行出发。其一是针对整体网页进行提前编码&#xff0c;其二是针对…...

小程序富文本图片大小问题

文章目录 概要uniapp小程序情况解决方法及完整示例 概要 在小程序使用富文本或者在nuiapp&#xff08;小程序的&#xff09;使用富文本都会转为 <rich-text nodes"<p class"p class">内容</p>”></rich-text>如果是这种情况的话在css…...

Diagrams——制作短小精悍的流程图

今天为大家分享的是一款轻量级的流程图绘制软件——Diagrams。 以特定的图形符号加上说明&#xff0c;表示算法的图&#xff0c;称为流程图或框图。流程图是流经一个系统的信息流、观点流或部件流的图形代表。我们常用流程图来说明某一过程。 流程图使用一些标准符号代表某些类…...

Elasticsearch基础条件查询

条件查询 query&#xff1a;查询 match&#xff1a;匹配 match_all&#xff1a;匹配所有 #第一种 GET /shopping/_search?q名字:张三#第二种 GET /shopping/_search {"query": {"match": {"名字": "张三"}} }#全量查询 match_all G…...

【SAP-ABAP】SAP与外围系统对接方式

SAP作为接受方 1.JAVA直接配置IP、账号、密码&#xff08;有些人叫SAPWEBAPI&#xff09;调用SAP里面的RFC函数 2.SAP发布RFC函数&#xff0c;配置webservice地址 3.SAP发布ODATA服务 4.SAP发布restful的http服务 5.我不太懂的UI5和FIORI本质好像也是odata服务 6.IDOC SA…...