Hướng dẫn tối thượng về hiệu năng mạng Linux
(ntk148v.github.io)- Tối ưu hiệu năng mạng Linux là công việc diễn giải luồng gói tin đi qua NIC ring buffer, IRQ, NAPI, softIRQ, qdisc, TCP buffer đến socket của ứng dụng theo góc nhìn các điểm nghẽn
- Trên đường nhận, NIC ghi gói tin vào RAM bằng DMA và phát sinh HardIRQ, trình điều khiển lên lịch NAPI để làm trống ring buffer trong
NET_RX_SOFTIRQrồi chuyển tiếp qua các tầng IP/TCP và vào bộ đệm nhận của socket ethtool,/proc/net/softnet_stat,ss,netstat,sysctllà điểm khởi đầu cho việc quan sát và điều chỉnh; các trục chính gồm interrupt coalescing, IRQ affinity, RSS/RPS/RFS/aRFS,netdev_budget,netdev_max_backlog,txqueuelen, và TCP read/write buffer- Không có một cấu hình duy nhất áp dụng cho mọi hệ thống; tăng ring buffer có thể giảm drop nhưng làm tăng độ trễ, còn interrupt coalescing có thể giảm mức sử dụng CPU và HardIRQ nhưng phải đánh đổi bằng độ trễ
- Xử lý gói tin hiệu năng cao có thể mở rộng với các lựa chọn như
PACKET_MMAP, DPDK,PF_RING, XDP/AF_XDP, nhưng mỗi cơ chế bypass kernel, zero-copy hay đường đi nhanh trong kernel đều khác nhau về phụ thuộc phần cứng, mức chiếm dụng CPU và yêu cầu phiên bản kernel
Đường nhận Linux: từ NIC đến socket
- Thiết bị mạng phát sinh IRQ để báo gói tin đến, và ánh xạ IRQ của Linux được lưu trong
/proc/interrupts - Trình xử lý IRQ chạy ở mức ưu tiên rất cao và trong một số trường hợp chặn việc phát sinh thêm IRQ, vì vậy trình điều khiển sẽ dời các tác vụ dài ra ngoài ngữ cảnh IRQ
- Việc xử lý trì hoãn này dùng softIRQ; trong xử lý nhận mạng, kernel tạo các luồng
ksoftirqd/<cpu-number>,softnet_data, vàpoll_listcho từng CPU net_dev_initđăng kýNET_RX_SOFTIRQvào hệ thống softIRQ, và trình xử lý tương ứng lànet_rx_action-
Gói tin đến và xử lý NAPI
- NIC ghi dữ liệu nhận từ mạng vào ring buffer trong RAM bằng DMA
- Một số NIC là NIC multiqueue với nhiều ring buffer
- Khi NIC phát sinh HardIRQ, trình xử lý IRQ của trình điều khiển sẽ chạy
- Trình điều khiển xóa IRQ của NIC và gọi
napi_scheduleđể khởi động vòng poll softIRQ của NAPI napi_schedulethêm cấu trúc NAPI poll của trình điều khiển vàopoll_listcủa CPU hiện tại và đặt pending bit cho softIRQ- Khi
ksoftirqdgọi__do_softirq, trình xử lýnet_rx_actioncủaNET_RX_SOFTIRQđang ở trạng thái pending sẽ được thực thi
-
GRO và đi vào protocol stack
net_rx_actionkiểm tra NAPI poll list,budgetvà thời gian đã trôi qua để softIRQ không độc chiếm CPU- Hàm
pollcủa trình điều khiển thu hoạch gói tin từ ring buffer trong RAM - Gói tin được chuyển cho
napi_gro_receive - GRO(Generic Receive Offloading) là kỹ thuật offload dựa trên phần mềm, tái lắp ráp các gói nhỏ thành gói lớn để giảm số lượng gói mà ứng dụng phải xử lý
- Nếu GRO không giữ lại gói tin, nó sẽ đi lên trên protocol stack qua
netif_receive_skb
-
Phân nhánh theo việc RPS có được bật hay không
- Khi RPS bị tắt:
netif_receive_skbchuyển dữ liệu tới__netif_receive_core__netif_receive_corechuyển dữ liệu đến tap và các trình xử lý tầng giao thức đã đăng ký
- Khi RPS được bật:
netif_receive_skbchuyển dữ liệu đếnenqueue_to_backlog- Gói tin được đưa vào input queue theo từng CPU
- Cấu trúc NAPI của CPU từ xa được thêm vào
poll_listcủa CPU đó, và một IPI được xếp hàng để đánh thức luồng softIRQ của CPU từ xa ksoftirqdcủa CPU từ xa sẽ thu hoạch gói tin từ CPU input queue bằng hàm pollprocess_backlog
- Khi RPS bị tắt:
-
IP, TCP, bộ đệm nhận của socket
- Gói tin được nhận ở tầng IPv4 qua
ip_rcvvà đi qua netfilter cùng tối ưu hóa định tuyến - Dữ liệu hướng tới hệ thống hiện tại được chuyển tiếp lên các tầng giao thức cao hơn như UDP hoặc TCP
- Trên đường nhận TCP, gói tin đi qua
tcp_v4_rcv, máy trạng thái hữu hạn TCP và bước tra cứu socket trước khi vào bộ đệm nhận - Kích thước bộ đệm nhận tuân theo quy tắc
tcp_rmem - Nếu
tcp_moderate_rcvbufđược bật, kernel sẽ tự động điều chỉnh bộ đệm nhận tcp_rmemchứa giá trị tối thiểu, mặc định và tối đa của bộ đệm nhận cho socket TCP- Dùng
SO_RCVBUFsẽ tắt tự động điều chỉnh bộ đệm nhận của socket đó net.core.rmem_maxlà giới hạn trên của kích thước bộ đệm nhận TCP; cửa sổ lớn hơn cho phép gửi nhiều dữ liệu hơn trước khi truyền ACK, nhờ đó giảm độ trễ và tăng thông lượng
- Gói tin được nhận ở tầng IPv4 qua
Đường gửi Linux: từ ứng dụng đến NIC
- Đường gửi đơn giản hơn đường nhận nhưng có sự tham gia của qdisc, TCP write buffer, DMA và IRQ
- Khi ứng dụng gửi thông điệp bằng lời gọi như
sendmsg, đường gửi TCP sẽ cấp phátskb_buff - Gói tin được đưa vào socket write buffer có kích thước
tcp_wmemtcp_wmemchứa giá trị tối thiểu, mặc định và tối đa của bộ đệm gửi cho socket TCP- Kernel điều chỉnh động kích thước bộ đệm gửi TCP trong khoảng từ giá trị tối thiểu đến tối đa
- Dùng
SO_SNDBUFsẽ tắt tự động điều chỉnh bộ đệm gửi của socket đó net.core.wmem_maxlà giới hạn trên của kích thước bộ đệm gửi TCP
- TCP header và IP header được tạo ra, sau đó đi qua
LOCAL_OUT, định tuyến,POST_ROUTING, fragmentation rồi hàm gửi L2 được gọi quadev_queue_xmit - qdisc đầu ra sử dụng độ dài
txqueuelenvà thuật toándefault_qdisc - Trình điều khiển đưa gói tin vào TX ring buffer và thực hiện
NET_TX_SOFTIRQsau timeouttx-usecshoặc sautx-frames - NIC lấy gói tin từ RAM bằng DMA để truyền đi, rồi phát sinh HardIRQ sau khi truyền xong
- Trình điều khiển xử lý IRQ này và lên lịch hệ thống NAPI poll để giải phóng RAM
Công cụ quan sát và các điểm kiểm tra cơ bản
-
/proc/net/softnet_stat- Mỗi dòng trong
/proc/net/softnet_statđại diện cho một lõi CPU, bắt đầu từ CPU0 - Thống kê của từng cột được cung cấp ở dạng hexadecimal
- Cột thứ 1 là số frame mà trình xử lý ngắt đã nhận
- Cột thứ 2 là số frame bị drop do vượt quá
netdev_max_backlog - Cột thứ 3 là số lần
ksoftirqddùng hếtnetdev_budgethoặc thời gian CPU dù vẫn còn việc phải xử lý - Các cột còn lại có thể khác nhau tùy theo phiên bản Linux
- Mỗi dòng trong
-
/proc/net/sockstatvàss- Trong
/proc/net/sockstat, hãy kiểm tra trườngmem - Giá trị này được tính bằng cách cộng tổng
sk_buff->truesizecủa tất cả socket sslà công cụ dump thống kê socket, có thể hiển thị thông tin tương tựnetstatcùng với nhiều thông tin TCP và trạng thái hơnss -tmdùng để kiểm tra mức sử dụng bộ nhớ của socket TCPrmem_alloc: bộ nhớ được cấp phát cho packet nhậnrcv_buf: tổng bộ nhớ có thể cấp phát cho packet nhậnwmem_alloc: bộ nhớ dùng cho packet gửi đã được chuyển xuống layer 3snd_buf: tổng bộ nhớ có thể cấp phát cho packet gửiwmem_queued: bộ nhớ được cấp phát cho packet gửi chưa được chuyển xuống layer 3sock_drop: số packet bị drop trước khi được demultiplex tới socket
- Trong
-
netstatvàsysctlnetstatlà công cụ dòng lệnh xuất các kết nối mạng đang mở và thống kê protocol stack, đồng thời lấy thông tin từ hệ thống tệp/proc/net//proc/net/dev: thông tin thiết bị/proc/net/tcp: thông tin socket TCP/proc/net/unix: thông tin Unix domain socketsysctllà lệnh thay đổi thiết lập hệ thống và mạng thay vì ghi trực tiếp giá trị vào hệ thống tệp/procsysctl -w variable=valuedùng cho thay đổi tạm thời; với thay đổi vĩnh viễn, chỉnh sửa/etc/sysctl.confrồi áp dụng bằngsysctl -p
Điều chỉnh ring buffer NIC và interrupt
-
Ring buffer NIC
- RX ring buffer là một circular buffer FIFO kích thước cố định nằm trong RAM
- Bản thân ring buffer không chứa dữ liệu packet mà chứa các descriptor trỏ tới
skbđã được đưa vào RAM bằng DMA - Nếu thấy drop hoặc overrun, có thể tăng kích thước queue, nhưng tác dụng phụ là độ trễ có thể tăng
- Trong nhiều trường hợp, chỉ cần tăng kích thước buffer nhận là có thể ngăn packet drop, đồng thời cho kernel thêm chút thời gian để làm trống buffer
- Việc kiểm tra và thay đổi được thực hiện bằng
ethtool ethtool -g eth3: kiểm tra kích thước ring RX/TX hiện tại và giá trị tối đaethtool -G eth3 rx 8192 tx 8192: tăng buffer RX/TX lên giá trị tối đa- Theo dõi bằng
ethtool -S eth3và các bộ đếm nhưerr,drop,over,miss,timeout,reset,collis
-
Gộp ngắt phần cứng
- NIC có thể tích lũy các reference packet trong RX ring buffer cho đến khi đạt điều kiện timeout
rx-usecshoặcrx-framesrồi mới phát sinh HardIRQ; điều này được gọi là Interrupt coalescence - Nếu ngắt quá sớm, kernel sẽ thường xuyên bị gián đoạn khỏi công việc đang chạy, làm giảm hiệu năng hệ thống
- Nếu ngắt quá muộn, có thể không rút traffic khỏi NIC đủ nhanh, dẫn đến ghi đè và mất traffic
- Việc điều chỉnh gộp ngắt có thể giảm mức sử dụng CPU và HardIRQ, đồng thời tăng throughput, nhưng có thể phải đánh đổi bằng độ trễ
- Có thể kiểm tra tham số coalesce bằng
ethtool -c eth3, và thay đổi nhưethtool -C eth3 adaptive-rx off rx-usecs 0 rx-frames 0 - Chế độ adaptive cho phép card động ước lượng thiết lập coalescing dựa trên mẫu traffic và mẫu nhận của kernel
- NIC có thể tích lũy các reference packet trong RX ring buffer cho đến khi đạt điều kiện timeout
IRQ affinity và phân tán tải giữa các CPU
-
IRQ affinity
- IRQ có thuộc tính
smp_affinityxác định các lõi CPU có thể chạy ISR của IRQ đó - Căn chỉnh interrupt affinity và application thread affinity theo các lõi CPU cụ thể có thể cải thiện hiệu năng ứng dụng nhờ chia sẻ cache line
- Mặc định, việc này do daemon
irqbalanceđiều khiển - Trước khi điều chỉnh thủ công, cần dừng
irqbalance /proc/irq/<IRQ_NUMBER>/smp_affinitylưu bitmask hexadecimal biểu thị các lõi CPU- Trên máy chủ 4 lõi, giá trị mặc định
fnghĩa là IRQ có thể được xử lý trên mọi CPU echo 1 > /proc/irq/32/smp_affinitysẽ buộc chỉ dùng CPU0- Trên hệ thống có hơn 32 lõi, các nhóm 32-bit được phân tách bằng dấu phẩy
- IRQ affinity chỉ có thể tăng hiệu năng trong những cấu hình rất cụ thể và workload được xác định trước, nên có thể là con dao hai lưỡi
- IRQ có thuộc tính
-
RSS
- Trên NIC tốc độ cao, nếu chỉ dùng một queue và một CPU để nhận packet, một lõi có thể phải gánh toàn bộ trách nhiệm xử lý dữ liệu trong khi các lõi khác nhàn rỗi
- RSS(Receive-side scaling) là công nghệ NIC cho phép phân tán traffic qua nhiều queue gửi/nhận
- NIC tính hash dựa trên source/destination IP và source/destination port TCP/UDP, gán packet của cùng một flow vào một queue duy nhất, đồng thời phân bố các flow tương đối đồng đều giữa các queue
- RSS mang lại lợi ích xử lý nhận song song trong môi trường multiprocessing
- Theo tài liệu Linux kernel, RSS nên được bật khi độ trễ là yếu tố quan trọng hoặc khi xử lý ngắt nhận là nút thắt cổ chai; trong mạng độ trễ thấp, cấu hình tối ưu là cấp phát số queue bằng với số CPU của hệ thống
-
RPS, RFS, aRFS
- RPS(Receive Packet Steering) gần như là một triển khai phần mềm của RSS
- Trong khi RSS chọn queue và CPU sẽ chạy trình xử lý ngắt phần cứng, RPS chọn CPU sẽ thực hiện xử lý giao thức ở phía trên trình xử lý ngắt
- Cần
CONFIG_RPSvà mặc định được bật trên SMP - Việc cấu hình được thực hiện bằng bitmap CPU trong
/sys/class/net/<dev>/queues/rx-<n>/rps_cpus - Nếu đã có RSS thì có thể không cần, nhưng vẫn hữu ích khi số CPU nhiều hơn số queue
- RFS(Receive Flow Steering) mở rộng RPS đến mức locality của ứng dụng
- RPS phân tán packet theo flow nhưng không xét đến việc ứng dụng không gian người dùng đang chạy trên CPU nào
- RFS duy trì
rps_sock_flow_table, là bảng flow-to-CPU toàn cục - Có thể điều chỉnh kích thước bảng bằng
net.core.rps_sock_flow_entries rps_dev_flow_tabletheo từng queue được dùng để giảm vấn đề sai thứ tự do packet còn tồn khi scheduler chuyển ứng dụng sang CPU mới- aRFS(Accelerated RFS) là cơ chế cân bằng tải tăng tốc bằng phần cứng cho RFS
- Nó gửi packet trực tiếp tới CPU gần với thread đang tiêu thụ dữ liệu, nên có thể cho hiệu năng tốt hơn RFS
- Cần
ndo_rx_flow_steer,ntuplefiltering của NIC vàCONFIG_RFS_ACCEL - Ánh xạ giữa CPU và queue được tự động suy ra từ IRQ affinity của từng queue nhận, nên không cần cấu hình thêm
softIRQ, tinh chỉnh qdisc và bộ đệm TCP
-
ngân sách softIRQ
- Routine polling NAPI bị giới hạn bởi
netdev_budget_usecs,netdev_budget,dev_weightđể softIRQ không chiếm dụng CPU - Giá trị mặc định của
net.core.netdev_budgetlà 300, nghĩa là tiến trình softIRQ sẽ làm trống 300 thông điệp từ NIC trước khi rời CPU net.core.netdev_budget_usecslà số micro giây tối đa của một chu kỳ polling NAPInet.core.dev_weightlà số lượng gói tối đa trên mỗi CPU mà kernel có thể xử lý trong ngắt NAPI- Nếu các cột khác ngoài cột thứ 1 trong
/proc/net/softnet_stattăng lên thì có thể cần thay đổi budget, dù mức tăng nhỏ có thể là bình thường
- Routine polling NAPI bị giới hạn bởi
-
qdisc ingress và
netdev_max_backlognetdev_max_backloglà hàng đợi nội bộ trong kernel, nơi lưu lượng được lưu sau khi nhận từ NIC nhưng trước khi được xử lý bởi stack giao thức như IP/TCP- Mỗi lõi CPU có một backlog queue riêng
- Nếu interface nhận gói nhanh hơn tốc độ kernel có thể xử lý, hàng đợi phía INPUT sẽ đầy đến
netdev_max_backlog, và các gói vượt quá sẽ bị drop - Giá trị mặc định là 1000, có thể không đủ cho nhiều interface 1Gbps hoặc một interface 10Gbps
- Cột thứ 2 của
/proc/net/softnet_statlà bộ đếm tăng lên khi backlog queue bị tràn - Thay đổi giá trị bằng
sysctl -w net.core.netdev_max_backlog <value>
-
qdisc egress,
txqueuelen,default_qdisctxqueuelenthiết lập số gói được phép trong hàng đợi truyền của kernel trên thiết bị giao diện mạng- Giá trị mặc định có thể là 1000 tùy theo driver của interface
- Thay đổi bằng
ifconfig <interface> txqueuelen value, và kiểm tra RX/TX dropped trongip -s link default_qdisclà queuing discipline mặc định sẽ dùng cho thiết bị mạng- Có thể chỉ định các lựa chọn thay thế như
sfq,codel,fq_codelthay chopfifo_fast - Kiểm tra các chỉ số như dropped, overlimits, requeues trong
tc -s qdisc ls dev <interface>
-
bộ đệm đọc/ghi TCP và hàng đợi kết nối
tcp_rmemvàtcp_wmemlần lượt định nghĩa giá trị tối thiểu, mặc định và tối đa của bộ đệm nhận/gửi TCP- Thay đổi như sau
sysctl -w net.ipv4.tcp_rmem="min default max"sysctl -w net.ipv4.tcp_wmem="min default max"
- Kiểm tra trạng thái sử dụng bộ đệm bằng
/proc/net/sockstat - Accept queue và SYN queue chịu ảnh hưởng của
net.core.somaxconnvànet.ipv4.tcp_max_syn_backlog net.core.somaxconnlà giới hạn trên của tham số backlog tronglisten(), và nếu thay đổi giá trị này thì ứng dụng cũng phải đổi sang giá trị tương thíchnet.ipv4.tcp_syncookiesbật hoặc tắt SYN cookie, hữu ích để bảo vệ trước tấn công SYN floodnet.ipv4.tcp_congestion_controlthiết lập thuật toán congestion control sẽ dùng cho các kết nối mới
NUMA và hiệu năng mạng
- NUMA (Non-uniform memory access) là kiến trúc bộ nhớ trong đó bộ xử lý có thể truy cập local memory nhanh hơn non-local memory
- Trong xử lý mạng, CPU phải truy cập bộ nhớ ring buffer, nên NUMA locality có thể ảnh hưởng đến hiệu năng mạng
- NUMA chia CPU, bộ nhớ và thiết bị thành nhiều node, và hoạt động như nhiều máy tính nhỏ có interconnect tốc độ cao và cùng một OS
- Trên hệ thống NUMA, mục tiêu tinh chỉnh là gom ngắt của thiết bị vào các lõi CPU thuộc cùng node với thiết bị đó
- Tuy vậy, hệ thống NUMA có thể tương tác không tốt với ứng dụng thời gian thực và gây ra độ trễ sự kiện không mong muốn
- Có thể kiểm tra NUMA node tại
/sys/devices/system/node/node* - Có thể kiểm tra locality của thiết bị tại
/sys/class/net/<interface>/device/numa_node-1nghĩa là nền tảng phần cứng thực tế không phải NUMA, hoặc kernel đang mô phỏng NUMA, hoặc thiết bị không có NUMA locality
- Linux kernel hỗ trợ NUMA từ phiên bản 2.5, và các bản phân phối dựa trên RedHat và Debian cung cấp
numactl,numad numadgiám sát topology hệ thống và mức sử dụng tài nguyên, rồi cố gắng đặt các tiến trình có tải CPU và bộ nhớ đủ lớn vào NUMA locality hiệu quả
Các lựa chọn xử lý gói tin nhanh hơn
-
AF_PACKETv4 vàPACKET_MMAPAF_PACKET v4là giao diện gói tin tốc độ cao của Linux, loại bỏ system call khỏi đường đi dữ liệu và mặc định sử dụng chế độ copy-mode- Khi dùng
PACKET_ZEROCOPY, có thể sử dụng chế độ zero-copy thực sự bằng cách ánh xạ DMA packet buffer vào không gian người dùng - Đường đi thông thường từ file read đến socket send cần context switch giữa user mode và kernel mode cùng nhiều lần sao chép dữ liệu
- zero-copy loại bỏ các lần sao chép dữ liệu dư thừa để tăng hiệu năng
PACKET_MMAPlà API Linux dành cho packet sniffing tốc độ cao- Cung cấp ring buffer được
mmapdùng chung giữa không gian người dùng và kernel - Giảm system call và việc sao chép giữa không gian người dùng với kernel khi gửi/nhận gói tin
-
DPDK
- DPDK(Data Plane Development Kit) là thư viện không gian người dùng và framework driver cho xử lý gói tin tốc độ cao
- Mục tiêu là trao đổi gói mạng ở tốc độ native giữa NIC và ứng dụng người dùng
- Nhắm đến các NIC 10Gb hoặc 40Gb, với tốc độ là tiêu chí quan trọng nhất
- Tập trung vào packet forwarding chứ không phải network stack
- Khi DPDK điều khiển NIC, toàn bộ lưu lượng sẽ đi vòng qua kernel, và NIC đó sẽ không còn hiển thị với kernel
- Cổng sẽ được unbind khỏi driver của Linux kernel và được quản lý bởi các driver như
vfio_pci,igb_uio,uio_pci_generic - Sau đó, DPDK PMD sẽ đảm nhiệm việc giao tiếp giữa ứng dụng và NIC
- DPDK cần cấu hình hugepages để cấp phát các chunk bộ nhớ lớn
- Thành phần chính:
- EAL: generic interface che giấu khác biệt môi trường
librte_ring: API FIFO lockless multi-producer, multi-consumerlibrte_mempool: cấp phát pool đối tượng bộ nhớlibrte_mbuf: tạo và thao tác buffer chứa gói mạnglibrte_timer: dịch vụ timer để thực thi hàm bất đồng bộ- PMD: driver để CPU liên tục poll NIC thay vì dùng interrupt
- Hạn chế:
- Phụ thuộc phần cứng rất lớn
- Phải dành riêng CPU core để chạy PMD và sẽ sử dụng 100% CPU
-
PF_RINGPF_RINGlà Linux kernel module và framework user-space để xử lý gói tin ở tốc độ cao và cung cấp API nhất quán cho các ứng dụng xử lý gói tinPF_RINGpoll gói tin từ NIC bằng Linux NAPI- NAPI sao chép gói từ NIC vào
PF_RINGcircular buffer, sau đó ứng dụng không gian người dùng đọc gói từ ring - Cấu trúc này có hai poller là ứng dụng và NAPI, nên CPU cycle sẽ được dùng cho polling
- Ưu điểm là có thể phân phối đồng thời incoming packet vào nhiều ring
- Với cấu trúc mô-đun, có thể dùng thêm các thành phần như ZC module, FPGA-based card module, Stack module, Timeline module, Sysdig module
PF_RINGđã giảm chi phí packet capture và userland forwarding, nhưng do cấu trúc hai actor gồm kernel sao chép từ NIC vào ring và userland đọc từ ring để xử lý nên hiệu năng tối ưu vẫn có giới hạnPF_RINGtừ phiên bản 7.5 đã bao gồm hỗ trợ adapterAF_XDP
-
XDP và
AF_XDP- XDP(eXpress Data Path) là một triển khai eBPF chặn gói tin ở giai đoạn sớm trong đường đi dữ liệu mạng của Linux
- XDP xử lý trực tiếp RX packet page bên trong hàm RX của device driver, trước khi SKB được cấp phát
- eBPF là bytecode sandboxed tùy biến chạy trong kernel
- Sử dụng 11 thanh ghi 64-bit và stack 512-byte
- Có thể biên dịch sang eBPF từ C, Lua, Go, P4, Rust... bằng LLVM backend
- Cung cấp in-kernel verifier và JIT compiler, đồng thời hỗ trợ các tính năng như map, tail call và helper
- Trường hợp sử dụng của XDP:
- pre-stack filtering để giảm thiểu DoS
- forwarding và load balancing
- kỹ thuật batching như GRO
- flow sampling và monitoring
- xử lý ULP
- XDP không phải là kernel bypass mà là fast path bên trong kernel stack, và không thay thế TCP/IP stack
- Không cần phần cứng chuyên dụng, nhưng có các yêu cầu như NIC multi-queue, TX/RX checksum offload, RSS, TSO
- Ưu điểm của XDP so với DPDK:
- có thể chọn busy polling hoặc interrupt driven networking
- không cần huge pages
- không có yêu cầu phần cứng đặc biệt
- không bắt buộc phải có CPU chuyên dụng
- không cần bơm lại gói tin từ ứng dụng userspace của bên thứ ba vào kernel
- không cần security model mới để truy cập phần cứng mạng
- không cần code/licensing của bên thứ ba
AF_XDPlà kiểu socket mới được giới thiệu trong Linux 4.18- Có thể tạo cấu trúc tương tự DPDK hoặc
AF_PACKETbằng cách tận dụng các chức năng của kernel mà không cần đi vòng qua kernel hoàn toàn - XDP program có thể dùng eBPF để redirect frame vào memory buffer của không gian người dùng
- DMA transfer hỗ trợ zero-copy bằng cách sử dụng bộ nhớ không gian người dùng
- Có thể đạt mức cải thiện hiệu năng gấp 3~20 lần so với
AF_PACKET - Hạn chế:
- Là dự án còn khá mới
- Để được hỗ trợ đầy đủ cần Linux kernel 5.4 trở lên
1 bình luận
Ý kiến trên Hacker News
Nếu tôi xem được tài liệu này chỉ vài tuần trước thì hẳn đã rất hữu ích
Tôi đã lấy báo giá appliance phần cứng từ nhiều nhà cung cấp để triển khai mã hóa liên kết L2 giữa các trung tâm dữ liệu, nhưng thấy chi phí quá đắt nên đã tự làm thử
Tôi cấu hình để chở các frame Ethernet trên mạng overlay WireGuard bằng phần cứng phổ thông và đạt 10Gbps; sau khoảng mười ngày làm việc, tôi triển khai được với chi phí rẻ hơn khoảng 70% so với đề xuất rẻ nhất và khoảng 95% so với đề xuất đắt nhất, nhưng phải đọc tài liệu chi tiết và thử nghiệm rất nhiều
Tôi muốn dùng nội dung bài này để kiểm chứng xem hiểu biết của mình có đúng không; nhìn qua thì có vẻ đầy hứa hẹn và khá toàn diện
Khi có nhiều giá trị có thể điều chỉnh đến mức này, tôi nghĩ có lẽ đáng để tạo phần mềm tự động tinh chỉnh
Có vẻ có thể dùng một cách tiếp cận giống gradient descent: chọn ngẫu nhiên một tham số trong whitelist, tăng hoặc giảm nhẹ trong phạm vi cho phép, đo hiệu năng trong một thời gian; nếu tệ đi thì hoàn nguyên, nếu tốt lên thì tiếp tục điều chỉnh
Bài viết thú vị, nhưng với tư cách kỹ sư phần mềm, tôi hiếm khi có cơ hội thực sự chạy các lệnh trong bài
Phần lớn hệ thống chạy trong các container là bản rút gọn của một Linux nào đó, không có quyền truy cập shell vào hệ thống vận hành, còn môi trường dev hay QA thì quá khác production về tải và nhiều mặt khác nên việc tái hiện lỗi thường không giúp được mấy
Rốt cuộc, cơ hội chạy thử các lệnh trong bài chỉ là khi nghịch hệ thống cá nhân; nếu làm kỹ sư nền tảng thì chắc sẽ hữu ích
Một trong những điểm tôi không thích lắm ở Kubernetes là mô hình mạng. Nó giả định chỉ có một card mạng, và ứng dụng đủ đơn giản để không cần biết gì về các tầng bên dưới
Toàn bộ mô hình mạng có vẻ còn nhiều chỗ để đại tu theo kiểu thập niên 2020 nhằm đơn giản hóa và cải thiện
net.core.wmem_maxđược mô tả là giới hạn trên của kích thước bộ đệm gửi TCP, và cũng cónet.ipv4.tcp_wmem, nên tôi có hai thắc mắcnet.core.wmem_max?net.core.wmem_maxđúng như tên gọi là giá trị tối đanet.ipv4.tcp_wmemlà một bộ ba giá trị gồm tối thiểu, mặc định, tối đa; giá trị tối đa được chỉ định ở đây không thể vượt quánet.core.wmem_maxnói trênTCP phải là cùng một giao thức, dù được chở trên IPv4 hay IPv6
Ví dụ: https://docs.redhat.com/en/documentation/red_hat_data_grid/7...
Phần hơi thiếu ở đây là gỡ lỗi và tinh chỉnh cho thông lượng trên 100Gbps
Khi phục vụ HTTP ở quy mô đó, nút thắt đầu tiên thường là băng thông bộ nhớ, nên nhiều trường hợp sẽ cần kTLS
Các công cụ như AMD μProf rất hữu ích cho việc gỡ lỗi, và profiling liên tục dựa trên eBPF cũng giúp hiểu chính xác chuyện gì đang xảy ra trong kernel và user space
Trông khá hay. Trong sự nghiệp của tôi đến nay, mỗi khi cần hiệu năng, thường tôi bắt đầu bằng bypass kernel