안녕하세요 여러분, 오늘은 사진 몇 장을 통해 XDP 기술에 대해 이야기해보겠습니다.
많은 Linux 개발자, 특히 네트워크 관련 개발에 종사하는 개발자는 XDP 기술에 익숙하지 않을 수 있습니다. Linux 개발자이고 XDP 기술을 모른다면 많은 기회를 놓칠 수 있습니다.
한 번은 XDP 기술을 적용하여 프로젝트를 최적화하고 네트워크 처리 성능을 3~4배 향상시키는 데 성공했습니다. 일부 사람들은 프로젝트의 원래 성능이 좋지 않다고 생각할 수 있으므로 개선의 여지가 상당히 큽니다.
현재 소프트웨어 아키텍처에서는 추가 최적화를 수행하더라도 성능 병목 현상을 제거하기가 쉽지 않을 것이라고 생각합니다. 보다 포괄적인 관점에서 이 문제를 해결하려면 보다 효율적인 아키텍처를 채택해야 합니다.
제 후속 프로젝트인 Magic Box에도 XDP 기술을 사용할 예정인데, XDP 기술을 사용한 후 Magic Box의 네트워크 성능이 약 3배 향상될 것으로 예상됩니다.
초고대역폭 네트워크 기술인 10G, 40G, 100G 네트워크의 출현으로 Linux 커널 프로토콜 스택은 점점 더 새로운 네트워크 기술의 개발에 적응할 수 없게 되었습니다. Linux 커널 프로토콜 스택은 병목 현상과 장애가 된 것 같습니다. 네트워크 성능의 낭비를 해결하기 위해 리눅스 커널은 새로운 기술인 Kernel Bypass 기술을 도입했습니다. Kernel Bypass 기술의 핵심 아이디어는 네트워크 데이터 패킷이 커널 프로토콜 스택을 건너 뛰고 처리된다는 것입니다. 이는 커널 프로토콜 스택을 방지하여 네트워크 성능을 크게 향상시킵니다.
XDP는 DPDK 기술에 대응하는 Linux 전용 커널 우회 기술입니다. DPDK는 성능 측면에서 우수한 성능을 발휘하지만 Linux 시스템에는 완전히 적합하지 않습니다.
XDP는 eBPF 메커니즘을 사용하여 커널 공간에서 고성능 패킷 처리 및 전달을 달성하는 Linux 커널 기술입니다.
XDP는 네트워크 성능을 크게 향상시키고 유연한 프로그래밍 인터페이스를 제공하여 사용자가 다양한 맞춤형 네트워크 기능을 구현할 수 있도록 합니다. 기존 사용자 공간 패킷 처리와 비교하여 XDP는 패킷 처리 지연 및 CPU 사용량을 효과적으로 줄일 수 있습니다.
XDP 기술 작업 모드:
기본 모드(고성능, 네트워크 카드 지원 필요) 드라이버 모드는 네트워크 카드 드라이버에서 XDP 프로그램을 실행하고 네트워크 카드 드라이버에서 네트워크 데이터 패킷을 리디렉션합니다. 이 모드는 더 많은 네트워크 카드를 지원하며 네트워크 성능이 뛰어납니다. 카드가 지원한다면 이 모드를 사용해 보십시오.
제거 모드(최고 성능, 최소 지원 네트워크 카드)는 XDP 프로그램을 네트워크 카드에서 직접 제거하므로, 지금은 이에 대해 논의하지 않습니다.
범용 모드(우수한 성능, 최고의 Linux 커널 지원) XDP 프로그램은 드라이버 지원 없이 Linux 커널 프로토콜 스택의 입구에서 실행됩니다. 성능은 XDP의 다른 두 모드보다 낮지만 XDP 범용 모드에서도 최고의 시스템 성능은 약간의 개선을 가져옵니다.
향후 XDP 기술에 관한 특별한 주제가 있을 예정이므로 여기서는 다루지 않겠습니다.
많은 학생들이 XDP와 AF_XDP 기술을 쉽게 혼동합니다.
AF_XDP는 소켓 기능을 통해 생성되어야 합니다.
으아악AF_XDP 기술에는 몇 가지 중요한 지식 포인트가 포함됩니다.
사진
UMEM 공유 메모리는 setockopt 함수를 통해 적용됩니다.
으아악UMEM 공유 메모리는 일반적으로 한 단위로 4K이고, 각 단위는 하나의 데이터 패킷을 저장할 수 있으며, UMEM 공유 메모리는 일반적으로 4096개 단위입니다.
수신 및 전송된 데이터 패킷은 UMEM 메모리 장치에 저장됩니다.
사용자 프로그램과 커널 모두 이 메모리 영역을 직접 운영할 수 있으므로 데이터 패킷을 보내고 받을 때 단순한 메모리 복사일 뿐이며 시스템 호출이 필요하지 않습니다.
用户程序需要维护一个UMEM内存使用记录,记录每一个UMEM单元是否已被使用,每个记录都会有一个相对地址,用于定位UMEM内存单元地址。
AF_XDP socket总共有4个无锁环形队列,分别为:
图片
环形队列创建方式:
//创建FILL RINGsetsockopt(fd, SOL_XDP, XDP_UMEM_FILL_RING,&umem->config.fill_size, sizeof(umem->config.fill_size)); //创建COMPLETION RINGsetsockopt(fd, SOL_XDP, XDP_UMEM_COMPLETION_RING,&umem->config.comp_size, sizeof(umem->config.comp_size));//创建RX RING setsockopt(xsk->fd, SOL_XDP, XDP_RX_RING,&xsk->config.rx_size, sizeof(xsk->config.rx_size));//创建TX RINGsetsockopt(xsk->fd, SOL_XDP, XDP_TX_RING, &xsk->config.tx_size, sizeof(xsk->config.tx_size));
4个环形队列实现方式基本相同,环形队列是对数组进行封装的数据结构,环形队列由5个重要部分组成:
生产者序号用于指示数组当前可生产的元素位置,如果队列已满,将不能再生产。
消费者序号用于指示当前可消费的元素位置,如果队列已空,将不能再消费。
队列长度即数组长度。
mask=len-1,生产者和消费者序号不能直接使用,需要配合掩码使用,producer,consumer和mask进行与运算,可以获取到数组的索引值。
数组的每一个元素记录了UMEM单元的相对地址,如果UMEM单元有发送和接收的数据包,还会记录数据包的长度。
环形队列的无锁化通过原子变量来实现,原子变量和原子操作在高性能编程中经常会用到。
AF_XDP接收数据包需要FILL RING,RX RING两个环形队列配合工作。
第一步:XDP程序获取可用UMEM单元。
FILL RING记录了可以用来接收数据包的UMEM单元数量,用户程序根据UMEM使用记录,定期的往FILL RING生产可用UMEM单元。
第二步:XDP填充新的接收数据包
XDP程序消费FILL RING中UMEM单元用于存放网络数据包,接收完数据包后,将UMEM单元和数据包长度重新打包,填充至RX RING队列,生产一个待接收的数据包。
第三步:用户程序接收网络数据包
用户程序检测到RX RING有待接的收数据包,消费RX RING中数据包,将数据包信息从UMEM单元中拷贝至用户程序缓冲区,同时用户程序需要再次填充FILL RING队列推动XDP继续接收数据。
图片
AF_XDP发送数据包需要COMP RING,TX RING两个环形队列配合工作。
第一步:用户程序确保有足够的UMEM发送单元
COMP RING记录了已完成发送的数据包(UMEM单元)数量,用户程序需要回收这部分UMEM单元,确保有足够的UMEM发送单元。
第二步:用户程序发送数据包
用户程序申请一个可用的UMEM单元,将数据包拷贝至该UMEM单元,然后生产一个待发送数据包填充值TX RING。
第三步:XDP发送数据包
XDP程序检测到TX RING中有待发送数据包,从TX RING消费一个数据包进行发送,发送完成后,将UMEM单元填充至COMP RING,生产一个已完成发送数据包,用户程序将对该数据包UMEM单元进行回收。
图片
AF_XDP之所以高效,主要有三大原因:
内核旁路技术在处理网络数据包的时候,可以跳过Linux内核协议栈,相当于走了捷径,这样可以降低链路开销。
用户程序和内核共享UMEM内存和无锁环形队列,采用mmap技术将内存进行映射,用户操作UMEM内存不需要进行系统调用,减少了系统调用上下文切换成本。
无锁环形队列采用原子变量实现,可以减少线程切换和上下文切换成本。
基于以上几点,AF_XDP必然是一个高性能的网络技术,由于目前没有一个能够测试XDP极限性能的测试环境,大家如果对AF_XDP技术感兴趣,可以自行上网搜索相关资料。
위 내용은 Linux 네트워크 성능의 왕인 XDP 기술에 대해 이야기해 보겠습니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!